wsdlpull svntrunk
SchemaParser.cpp
Go to the documentation of this file.
1/*
2 * wsdlpull - A C++ parser for WSDL (Web services description language)
3 * Copyright (C) 2005-2007 Vivek Krishna
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 *
19 */
20
22
23#ifndef _WIN32
24#include "xmlpull/ConfigFile.h"
25#endif
26
27//
28#include <climits>
29
30namespace Schema {
31using namespace std;
33 std::string tns,
34 std::ostream & log,
35 const std::string & s)
36 :tnsUri_(tns),
37 xParser_(parser),
38 elementQualified_ (false),
39 attributeQualified_ (false),
40 deleteXmlParser_(false),
41 resolveFwdRefs_(true),
42 level_(1),
43 logFile_(log),
44 confPath_(s)
45{
46 init();
47}
48
49SchemaParser::SchemaParser(const std::string &Uri,
50 std::string tns ,
51 std::ostream & log ,
52 const std::string & s)
53 :tnsUri_(tns),
54 xParser_(0),
55 elementQualified_ (false),
56 attributeQualified_ (false),
57 deleteXmlParser_(false),
58 resolveFwdRefs_(true),
59 level_(1),
60 logFile_(log),
61 confPath_(s)
62{
63 if(XmlUtils::fetchUri(Uri,fname_))
64 {
65 xmlStream_.open(fname_.c_str());
66 xParser_ = new XmlPullParser(xmlStream_);
68 xParser_->require(XmlPullParser::START_DOCUMENT, "", "");
69 while (!xmlStream_.fail() && xParser_->getEventType() != xParser_->END_DOCUMENT)
70 {
71 xParser_->nextTag();
72 if (xParser_->getEventType() == xParser_->START_TAG &&
73 xParser_->getName() == "schema")
74 {
75 deleteXmlParser_=true;
76 tnsUri_=tns;
77 break;
78 }
79 }
80
81 }
82 if(!deleteXmlParser_) //something wron while opening the schema file
83 {
84 delete xParser_;
85 xParser_=0;
86 }
87
88 init();
89 uri_ = Uri.substr(0,Uri.rfind('/') + 1);
90}
91
92void
93SchemaParser::init()
94{
95 lElems_.clear() ;
96 lAttributes_.clear();
97 lAttributeGroups_.clear();
98 importedSchemas_.clear();
99 constraints_.clear();
100
101 if (confPath_.empty()) {
102#if defined SCHEMADIR
103 confPath_ = SCHEMADIR;
104#else
105 confPath_ = "src/schemas";
106#endif
107 }
108
109 Element e("schema",
110 SchemaUri,
111 SchemaUri,
113 lElems_.push_back(e);
114
115
116
117#ifdef LOGGING
118 level_ = 2;
119#endif
120}
121
123{
124 //clear the Types table
125 typesTable_.clean();
126 if(deleteXmlParser_) {
127
128 delete xParser_;
129 xmlStream_.close();
130 }
131
132 for (ConstraintList::iterator ci=constraints_.begin();
133 ci != constraints_.end();
134 ci++)
135 delete *ci;
136 for (AttributeGroupList::iterator agi = lAttributeGroups_.begin();
137 agi != lAttributeGroups_.end();
138 agi++)
139 delete *agi;
140}
141
142
143/*
144 * Parses an schema definition.
145 * This is the main entry method for the schema parser
146 */
147bool
149{
150 int i = 0;
151 try {
152 if(!xParser_)
153 return false;
154 while (xParser_->getEventType() != xParser_->START_TAG)
155 xParser_->next();
156 xParser_->require(xParser_->START_TAG, Schema::SchemaUri, "schema");
157 int attcnt = xParser_->getAttributeCount();
158
159 //parse the schema tag's attributes
160 for (i = 0; i < attcnt; i++) {
161 std::string attName = xParser_->getAttributeName(i);
162 if ("targetNamespace" == attName)
163 //store the tns URI
164 tnsUri_ = xParser_->getAttributeValue(i);
165 if ("version" == attName)
166 version_ = xParser_->getAttributeValue(i);
167 if ("elementFormDefault" == attName){
168 if (xParser_->getAttributeValue(i) == "unqualified")
169 elementQualified_ = false;
170
171 else if (xParser_->getAttributeValue(i) == "qualified")
172 elementQualified_ = true;
173 }
174 if ("attributeFormDefault" == attName) {
175 if (xParser_->getAttributeValue(i) == "unqualified")
176 attributeQualified_ = false;
177
178 else if (xParser_->getAttributeValue(i) == "qualified")
179 attributeQualified_ = true;
180 }
181 }
182
183 for (i = xParser_->getNamespaceCount(xParser_->getDepth()) - 1;
184 i > xParser_->getNamespaceCount(xParser_->getDepth() - 1) - 1; i--)
185 if (xParser_->getNamespaceUri(i) == tnsUri_)
186 tnsPrefix_ = xParser_->getNamespacePrefix(i);
187 typesTable_.setTargetNamespace(tnsUri_);
188 xParser_->nextTag();
189
190 return parseSchema();
191 } catch (XmlPullParserException xpe){
192
193 logFile_ <<"Error parsing schema for namespace "<<tnsUri_<<std::endl;
194 logFile_ << xpe.description << " at "
195 << xpe.line << ":" << xpe.col
196 << std::endl;
197 return false;
198 }
199 catch(SchemaParserException spe) {
200
201 spe.line = xParser_->getLineNumber();
202 spe.col = xParser_->getColumnNumber();
203
204 logFile_ << spe.description << " at "
205 << spe.line << ":" << spe.col
206 << std::endl;
207
208 return false;
209 }
210}
211
212//this function handles the schema
213bool
214SchemaParser::parseSchema(std::string tag)
215{
216 try
217 {
218 do
219 {
220
221 if (xParser_->getEventType() == xParser_->END_TAG)
222 {
223 if (xParser_->getName() == tag)
224 break;
225 while (xParser_->getEventType() != xParser_->START_TAG)
226 xParser_->nextTag();
227 }
228
229 /*
230 This is the main loop
231 Depending on the tag encountered call the appropriate routines
232 Schema elements visible at this level
233 1. Global Element declarations
234 2. Global attribute declarations
235 3. Complex type and Simple type declarations
236
237 */
238 std::string elemName = xParser_->getName();
239 if (elemName == "element") {
240 bool fwd;
241 Element e = parseElement(fwd);
242 lElems_.push_back(e);
243 }
244 else if (elemName == "complexType")
245 {
246 XSDType *t = parseComplexType();
247 typesTable_.addType(t);
248 }
249 else if (elemName == "simpleType")
250 {
251 XSDType *t = parseSimpleType();
252 typesTable_.addType(t);
253 }
254 else if (elemName == "attribute") {
255 bool fwd;
256 lAttributes_.push_back(parseAttribute(fwd));
257 }
258 else if (elemName == "annotation"){
259 parseAnnotation();
260 }
261 else if (elemName == "import") {
262 parseImport();
263 }
264 else if (elemName=="include"){
265 parseInclude();
266 }
267 else if(elemName=="attributeGroup") {
268 AttributeGroup* ag = parseAttributeGroup();
269 if (ag)
270 lAttributeGroups_.push_back(ag);
271
272 }else if(elemName=="group") {
273
274 lGroups_.push_back(parseGroup());
275 Group & g=lGroups_.back();
276 //make this grp the owner of the content model
277 g.setContents(g.getContents(),false);
278 }
279 else if( elemName=="key") {
280
281 constraints_.push_back(parseConstraint(Schema::Key));
282 }
283 else if( elemName=="keyref") {
284 constraints_.push_back(parseConstraint(Schema::Keyref));
285 }
286 else if( elemName=="unique") {
287 constraints_.push_back(parseConstraint(Schema::Unique));
288 }else if (elemName=="redefine"){
289 parseRedefine();
290 }
291 else {
292 error("Unknown element "+ elemName,1);
293 break;
294 }
295 xParser_->nextTag();
296 }
297 while (true);
298 if ((importedSchemas_.size() == 0) &&
299 typesTable_.detectUndefinedTypes()){
300
301 typesTable_.printUndefinedTypes(logFile_);logFile_.flush();
302 error("Undefined Types in namespace "+tnsUri_);
303 }
304 if(shouldResolve())
305 {
306
307 resolveForwardElementRefs();
308 resolveForwardAttributeRefs();
309 }
310
311 }
312 catch(SchemaParserException spe)
313 {
314 spe.line = xParser_->getLineNumber();
315 spe.col = xParser_->getColumnNumber();
316
317 logFile_ << spe.description << " at "
318 << spe.line << ":" << spe.col
319 << std::endl;
320
321 return false;
322 }
323 return true;
324}
325
326
327void SchemaParser::parseAnnotation()
328{
329
330 do
331 {
332 xParser_->nextToken();
333 if (xParser_->getEventType() == xParser_->END_TAG
334 && xParser_->getName() == "annotation")
335 break;
336 }
337 while (true);
338}
339
340
341ComplexType *
342SchemaParser::parseComplexType()
343{
344 ComplexType *newType = new ComplexType(tnsUri_);
345 int attcnt = xParser_->getAttributeCount();
346 for (int i = 0; i < attcnt; i++)
347 {
348 if ("name" == xParser_->getAttributeName(i))
349 newType->setName(xParser_->getAttributeValue(i));
350
351 if ("mixed" == xParser_->getAttributeName(i) &&
352 (xParser_->getAttributeValue(i).empty() ||
353 xParser_->getAttributeValue(i)=="true"))
354
355 newType->setContentModel(Schema::Mixed);
356 }
357
358
359 do
360 {
361 //begin parsing the complex type's children
362 xParser_->nextTag();
363 if (xParser_->getEventType() == xParser_->END_TAG)
364 {
365 if (xParser_->getName() == "complexType")
366 break;
367
368 //if an end tag is seen proceed till next start tag
369 while (xParser_->getEventType() != xParser_->START_TAG)
370 xParser_->nextTag();
371 }
372 std::string elemName = xParser_->getName();
373
374
375 if (elemName == "all"){
376 ContentModel * cm= new ContentModel(Schema::All);
377 newType->setContents(cm);
378 parseContent(cm);
379 }
380 else if (elemName == "sequence"){
381 ContentModel * cm= new ContentModel(Schema::Sequence);
382 newType->setContents(cm);
383 parseContent(cm);
384 }
385 else if (elemName == "choice"){
386 ContentModel * cm= new ContentModel(Schema::Choice);
387 newType->setContents(cm);
388 parseContent(cm);
389 }
390 else if (elemName == "attribute") {
391 bool f=false;
392 Attribute a=parseAttribute(f);
393 newType->addAttribute(a,f);
394 }else if (elemName=="attributeGroup"){
395 parseAttributeGroup(newType);
396 }
397 else if (elemName=="group"){
398 //TODO
399 ContentModel* cm= new ContentModel(Schema::Sequence);
400 newType->setContents(cm);
401 parseGroup(cm);
402 }
403 else if (elemName == "anyAttribute")
404 addAnyAttribute(newType);
405
406 else if (elemName == "complexContent")
407 parseComplexContent(newType);
408
409 else if (elemName == "simpleContent")
410 parseSimpleContent(newType);
411
412 else if (xParser_->getName() == "annotation")
413 parseAnnotation();
414
415 else
416 error("Unexpected tag: '"+elemName+"' in "+newType->getName() );
417 }
418 while (true);
419 makeListFromSoapArray(newType);
420 return newType;
421}
422
423AttributeGroup*
424SchemaParser::parseAttributeGroup(ComplexType* cType)
425{
426 std::string name,ref;
427 ref = xParser_->getAttributeValue("", "ref");
428 if (!ref.empty())
429 {
430 Qname agRef(ref);
431 AttributeGroup *ag= getAttributeGroup(agRef);
432 if(cType && ag){
433
434 for(list<Attribute>::iterator ai= ag->begin();
435 ai!=ag->end();
436 ai++)
437 cType->addAttribute(*ai);
438 }
439 else if (cType){
440 cType->addAttributeGroupName(ref);
441 }
442 xParser_->nextTag();
443 return ag;
444 }
445
446 name = xParser_->getAttributeValue("", "name");
447 AttributeGroup *ag = new AttributeGroup(name);
448 xParser_->nextTag();
449 while (xParser_->getName() == "annotation")
450 {
451 parseAnnotation();
452 xParser_->nextTag();
453 }
454 std::string elemName=xParser_->getName();
455 while (!((xParser_->getEventType() == xParser_->END_TAG) &&
456 (elemName == "attributeGroup"))){
457
458 if(elemName=="attribute"){
459 bool fwd;
460 ag->addAttribute(parseAttribute(fwd));
461 }else if(elemName=="attributeGroup"){
462 AttributeGroup* ag1=parseAttributeGroup();
463 for(list<Attribute>::iterator ai= ag1->begin();
464 ai!=ag1->end();
465 ai++)
466 ag->addAttribute(*ai);
467 }else if(elemName=="anyAttribute"){
468 ag->addAttribute(addAnyAttribute(cType));
469 }
470 xParser_->nextTag();
471 elemName=xParser_->getName();
472 }
473
474 if(cType){
475
476 for(list<Attribute>::iterator ai= ag->begin();
477 ai!=ag->end();
478 ai++)
479 cType->addAttribute(*ai);
480 delete ag;//dont store anonymous attribute groups
481 ag = 0;
482 }
483 return ag;
484}
485
486Group
487SchemaParser::parseGroup(ContentModel* c)
488{
489 int minimum = 1, maximum = 1;
490 std::string tmp, name,ref;
491
492 tmp = xParser_->getAttributeValue("", "minOccurs");
493 if (!tmp.empty())
494 minimum = XmlUtils::parseInt(tmp);
495 tmp = xParser_->getAttributeValue("", "maxOccurs");
496 if (!tmp.empty()) {
497 if ("unbounded" == tmp)
498 maximum = UNBOUNDED;
499 else
500 maximum = XmlUtils::parseInt(tmp);
501 }
502 ref = xParser_->getAttributeValue("", "ref");
503 if (!ref.empty()) {
504
505 Qname gName(ref);
506 xParser_->nextTag();
507 Group* gRef=getGroup(gName);
508 if(gRef){
509 Group g(*gRef);
510 if(c)
511 c->addGroup(g,true);
512 return g;
513 }
514 else{
515 Group g(gName.getLocalName(),minimum,maximum);
516 if(c)
517 c->addGroup(g,true);
518 return g;
519 }
520 }
521
522 name = xParser_->getAttributeValue("", "name");
523 Group g(name,minimum,maximum);
524 xParser_->nextTag();
525 while (xParser_->getName() == "annotation") {
526 parseAnnotation();
527 xParser_->nextTag();
528 }
529
530 std::string elemName = xParser_->getName();
531 ContentModel * cm=0;
532 if (elemName == "all"){
533 cm = new ContentModel(Schema::All);
534 }
535 else if (elemName == "sequence"){
536 cm= new ContentModel(Schema::Sequence);
537 }
538 else if (elemName == "choice"){
539 cm= new ContentModel(Schema::Choice);
540 }
541 g.setContents(cm,true);
542 parseContent(cm);
543 xParser_->nextTag();
544
545 if(c)
546 c->addGroup(g,false);
547 return g;
548}
549
550void
551SchemaParser::parseContent(ContentModel * cm)
552{
553 int minimum = 1, maximum = 1;
554 std::string tmp;
555
556 tmp = xParser_->getAttributeValue("", "minOccurs");
557 if (!tmp.empty())
558 minimum = XmlUtils::parseInt(tmp);
559 tmp = xParser_->getAttributeValue("", "maxOccurs");
560 if (!tmp.empty())
561 {
562 if ("unbounded" == tmp)
563 maximum = UNBOUNDED;
564 else
565 maximum = XmlUtils::parseInt(tmp);
566 }
567 cm->setMin(minimum);
568 cm->setMax(maximum);
569
570 xParser_->nextTag();
571 while (xParser_->getName() == "annotation")
572 {
573 parseAnnotation();
574 xParser_->nextTag();
575 }
576
577 while (!((xParser_->getEventType() == xParser_->END_TAG) &&
578 (xParser_->getName() == "choice"
579 || xParser_->getName() == "sequence"
580 || xParser_->getName() == "all")))
581 {
582 if (xParser_->getName() == "element") {
583 bool f=false;
584 Element e =parseElement(f);
585 cm->addElement(e);
586 }else if(cm->getCompositor()!=Schema::All){
587
588 if (xParser_->getName() == "any")
589 addAny(cm);
590 else if (xParser_->getName() == "choice"){
591 ContentModel * cmc= new ContentModel(Schema::Choice);
592 cm->addContentModel(cmc);
593 parseContent(cmc);
594 }
595 else if (xParser_->getName() == "sequence"){
596 ContentModel * cms= new ContentModel(Schema::Sequence);
597 cm->addContentModel(cms);
598 parseContent(cms);
599 }
600 else if (xParser_->getName() == "group"){
601 parseGroup(cm);
602 }
603 else if(xParser_->getName() == "annotation") {
604 parseAnnotation();
605 }
606 else
607 error("parseContent: Unexpected tag "+xParser_->getName());
608 }else{
609
610 error("parseContent <all>:Syntax Error");
611 }
612 xParser_->nextTag();
613 }
614}
615
616Element
617SchemaParser::parseElement(bool & fwdRef)
618{
619 std::string name, fixedVal, defaultVal,
620 // the namespace of the element is the
621 // namespace of the sp that parsed it!
622 typeNs = tnsUri_,elemNs = tnsUri_;
623 Constraint* c=0;
624 int type_id = 0, minimum = 1, maximum = 1, attcnt;
625 Qname refName;
626 bool qualified = false,nill = false;
627 XSDType *elemType;
628 fwdRef=false;
629 attcnt = xParser_->getAttributeCount();
630 for (int i = 0; i < attcnt; i++)
631 {
632 std::string attName = xParser_->getAttributeName(i);
633 if ("name" == attName)
634 name = xParser_->getAttributeValue(i);
635
636 else if ("type" == attName)
637 {
638 Qname typeName(xParser_->getAttributeValue(i));
639 if (type_id > 0)
640 error
641 ("<element> : type and ref are mutually exclusive in element decl");
642 typeName.setNamespace(typeNs=xParser_->getNamespace(typeName.getPrefix()));
643 type_id = getTypeId(typeName, true);
644 if (type_id == 0)
645 error("<element>:Could not resolve type " +
646 typeName.getNamespace() + ":" +
647 typeName.getLocalName(),0);
648 }
649
650 else if ("form" == attName)
651 {
652 if ("qualified" == xParser_->getAttributeValue(i))
653 qualified = true;
654
655 else if ("unqualified" == xParser_->getAttributeValue(i))
656 qualified = false;
657 else
658 error("<element>:Invalid value for form in element " +
659 name,1);
660 }
661
662 else if ("ref" == attName)
663 {
664 if (!name.empty())
665 error
666 ("<element>:name and ref are mutually exclusive in element decl");
667 if (type_id > 0)
668 error
669 ("<element>:type and ref are mutually exclusive in element decl");
670 refName = xParser_->getAttributeValue(i);
671 refName.setNamespace(xParser_->getNamespace(refName.getPrefix()));
672 Element *e=0;
673 elemNs = refName.getNamespace();
674
675 if(refName.getNamespace()==tnsUri_){
676
677 e = const_cast<Element*>(getElement(refName));
678 if (e)
679 type_id = e->getType();
680 }
681 else{
682 //The referenced element may be in an imported schemaparser
683 int i=checkImport(refName.getNamespace());
684 if(i>=0 && importedSchemas_[i].sParser) {
685
686 e=const_cast<Element*>(importedSchemas_[i].sParser->getElement(refName));
687 if (e){
688 //if the type is in an imported schema then we must add a local reference to
689 // its type,because the type id as got by e->getType()
690 // is not valid in the current schema context
691 const XSDType* pType = importedSchemas_[i].sParser->getType(e->getType());
692 type_id= typesTable_.addExternalTypeId(e->getName()+"_"+e->getTypeNamespace(),
693 pType);
694 }
695 }
696 }
697
698 if (e == 0){
699
700 fwdRef=true;
701 name=refName.getLocalName();
702 lForwardElemRefs_.push_back(refName);
703 //this will be resolved later
704 }
705 else{
706 name = e->getName();
707 qualified = e->isQualified();
708 defaultVal = e->defaultVal();
709 fixedVal = e->fixedVal();
710 typeNs = e->getTypeNamespace();
711 elemNs = e->getNamespace();
712 }
713
714#ifdef LOGGING
715 logFile_<<elemNs<<":"<<name<<" -> element reference("<<type_id<<")"<<std::endl;
716#endif
717
718 }
719 else if ("minOccurs" == attName){
720 minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
721 }
722 else if ("maxOccurs" == attName){
723 if ("unbounded" == xParser_->getAttributeValue(i))
724 maximum = UNBOUNDED;
725 else
726 maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
727 if (maximum == -1){ //invalid value for maxOccurs
728 error("<element>:Invalid value for maxOccurs",1);
729 maximum=1;
730 }
731 }
732 else if ("default" == attName){
733 if (fixedVal.empty())
734 defaultVal = xParser_->getAttributeValue(i);
735
736 else
737 error("<element>:fixed and default cannot occur together");
738 }
739 else if ("fixed" == attName){
740 if (defaultVal.empty())
741 fixedVal = xParser_->getAttributeValue(i);
742
743 else
744 error("<element>:fixed and default cannot occur together");
745 }
746
747 else if ("substitutionGroup" == attName) {
748
749 //do nothing
750 }
751 else if ("nillable" == attName) {
752
753 //a nillable element need not have a type ,so set it to anyType id if nop type was given
754 nill = true;
755 minimum = 0;
756 }
757 else
758 error("<element>:Unsupported Attribute "+attName ,2) ;
759 }
760
761 do
762 {
763 xParser_->nextTag();
764 std::string elemName=xParser_->getName();
765 if (xParser_->getEventType() == xParser_->END_TAG) {
766 if (elemName == "element")
767 break;
768
769 //if an end tag is seen proceed till next start tag
770 while (xParser_->getEventType() != xParser_->START_TAG)
771 xParser_->nextTag();
772 }
773
774 if (elemName == "complexType"){
775 elemType = parseComplexType();
776 type_id = typesTable_.addType(elemType);
777 typeNs = elemType->getNamespace();
778 }
779 else if (elemName == "simpleType"){
780 elemType = parseSimpleType();
781 type_id = typesTable_.addType(elemType);
782 typeNs = elemType->getNamespace();
783 }
784 else if (elemName == "annotation"){
785 parseAnnotation();
786 }
787 else if( elemName=="key") {
788 if (c)
789 delete c;
790 c=parseConstraint(Schema::Key);
791 }
792 else if( elemName=="keyref") {
793 if (c)
794 delete c;
795 c=parseConstraint(Schema::Keyref);
796 }
797 else if( elemName=="unique") {
798 if (c)
799 delete c;
800 c=parseConstraint(Schema::Unique);
801 }
802 else{
803 error("<element> : syntax error or unkown tag :"+elemName);
804 }
805 }
806 while (true);
807
808 if (nill && type_id == 0) {
809 type_id = Schema::XSD_ANYTYPE;
810 }
811
812 constraints_.push_back(c);
813 Element e(name,
814 elemNs,
815 typeNs,
816 type_id,
817 minimum,
818 maximum,
819 qualified,
820 defaultVal,
821 fixedVal);
822 e.addConstraint(c);
823 return e;
824}
825
826Constraint*
827SchemaParser::parseConstraint(Schema::ConstraintType cstr)
828{
829 Constraint * c= new Constraint(cstr);
830 c->setName(xParser_->getAttributeValue("","name"));
831
832 do
833 {
834 xParser_->nextTag();
835 std::string elemName=xParser_->getName();
836 if (xParser_->getEventType() == xParser_->END_TAG) {
837 if ((cstr==Schema::Key && elemName == "key")
838 || (cstr==Schema::Keyref && elemName == "keyref")
839 || (cstr==Schema::Unique && elemName == "unique")) {
840 break;
841 }
842
843 //if an end tag is seen proceed till next start tag
844 while (xParser_->getEventType() != xParser_->START_TAG)
845 xParser_->nextTag();
846 }
847 if(elemName=="selector"){
848 c->setSelector(xParser_->getAttributeValue("", "xpath"));
849 xParser_->nextTag();
850 }
851 else if(elemName=="field"){
852 c->addField(xParser_->getAttributeValue("", "xpath"));
853 xParser_->nextTag();
854 }
855 }while (true);
856 return c;
857}
858
859
860Element
861SchemaParser::addAny(ContentModel* cm)
862{
863 std::string ns;
864
865 int type_id = Schema::XSD_ANY, minimum = 1, maximum = 1, attcnt;
866 //note processContents=lax .
867 attcnt = xParser_->getAttributeCount();
868 for (int i = 0; i < attcnt; i++)
869 {
870 std::string attr = xParser_->getAttributeName(i);
871 if ("namespace" == attr)
872 ns = xParser_->getAttributeValue(i);
873
874 else if ("minOccurs" == attr)
875 minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
876
877 else if ("maxOccurs" == attr)
878 {
879 if ("unbounded" == xParser_->getAttributeValue(i))
880 maximum = UNBOUNDED;
881 else
882 maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
883 if (maximum == -1){ //invalid value for maxOccurs
884 error("<element>:Invalid value for maxOccurs",1);
885 maximum=1;
886 }
887 }
888
889 else if ("processContents" == attr || "id" == attr) {
890
891 //do nothing
892 }
893 else
894 error("<any>:Unsupported Attribute "+attr,2);
895 }
896
897 xParser_->nextTag();
898 do
899 {
900 if (xParser_->getEventType() == xParser_->END_TAG)
901 {
902 if (xParser_->getName() == "any")
903 break;
904
905 }
906 xParser_->nextToken();
907 }while (true);
908
909
910 Element e(ns,
911 ns,
912 ns,
913 type_id,
914 minimum,
915 maximum);
916
917 cm->addElement(e);
918 return e;
919}
920
921
922Attribute
923SchemaParser::addAnyAttribute(ComplexType * cType)
924{
925 std::string ns;
926 int type_id = Schema::XSD_ANY,attcnt;
927 bool qualified = true;
928
929 //note processContents=lax .
930 attcnt = xParser_->getAttributeCount();
931 for (int i = 0; i < attcnt; i++)
932 {
933 std::string attr = xParser_->getAttributeName(i);
934 if ("namespace" == attr)
935 ns = xParser_->getAttributeValue(i);
936
937 else if ("processContents" == attr || "id" == attr)
938 {
939
940 //do nothing
941 }
942 else
943 error("<anyAttribute>:Unsupported Attribute "+attr,1);
944 }
945
946 Attribute a(ns,
947 type_id,
948 qualified);
949 if(cType)
950 cType->addAttribute(a);
951 xParser_->nextTag();
952 while (xParser_->getName() == "annotation")
953 {
954 parseAnnotation();
955 xParser_->nextTag();
956 }
957 return a;
958
959}
960
961
962//This function parses and attribute
963Attribute
964SchemaParser::parseAttribute(bool & fwdRef)
965{
966 std::string name, fixedVal, defaultVal;
967 int type_id = 0, attcnt;
968 bool qualified = false, use = false;
969 fwdRef=false;
970
971 Qname refAttribute;
972 attcnt = xParser_->getAttributeCount();
973 for (int i = 0; i < attcnt; i++) {
974 std::string attName = xParser_->getAttributeName(i);
975 std::string attNs=xParser_->getAttributeNamespace(i);
976 std::string attVal=xParser_->getAttributeValue(i);
977
978
979 if ("name" == attName)
980 name = attVal;
981 else if ("type" == attName) {
982 if (type_id > 0)
983 error("<attribute>:type and ref are mutually exclusive in element decl");
984 Qname typeName(attVal);
985 typeName.setNamespace(xParser_->
986 getNamespace(typeName.getPrefix()));
987 type_id = getTypeId(typeName, true);
988 if (type_id == 0)
989 error("<attribute>:Could not resolve type " +
990 typeName.getNamespace() +
991 ":" +typeName.getLocalName(),1);
992 }
993 else if ("form" == attName) {
994 if ("qualified" == attVal)
995 qualified = true;
996 else
997 qualified = false;
998 }
999 else if ("ref" == attName) {
1000 if (!name.empty())
1001 error("<attribute>:name and ref are mutually exclusive in element decl");
1002 if (type_id > 0)
1003 error("<attribute>:type and ref are mutually exclusive in element decl");
1004 refAttribute = attVal;
1005 refAttribute.setNamespace(xParser_->getNamespace(refAttribute.getPrefix()));
1006 Attribute *a =0;
1007 if(refAttribute.getNamespace()==tnsUri_){
1008 a=getAttribute(refAttribute);
1009 }else{
1010 int i=checkImport(refAttribute.getNamespace());
1011 if(i >=0 && importedSchemas_[i].sParser){
1012 a=importedSchemas_[i].sParser->getAttribute(refAttribute);
1013 }
1014 else
1015 a=0;
1016 }
1017
1018 if (a == 0){
1019 fwdRef = true;
1020 name=refAttribute.getLocalName();
1021 lForwardAttributeRefs_.push_back(refAttribute);
1022 }
1023 else{
1024 name = a->getName();
1025 type_id = a->getType();
1026 qualified = a->isQualified();
1027 if (defaultVal.empty())
1028 defaultVal = a->defaultVal();
1029 if (fixedVal.empty())
1030 fixedVal = a->fixedVal();
1031 }
1032 }
1033 else if ("default" == attName) {
1034 if (fixedVal.empty())
1035 defaultVal = attVal;
1036 else
1037 error
1038 ("<attribute>:fixed and default cannot occur together");
1039 }
1040 else if ("fixed" == attName) {
1041 if (defaultVal.empty())
1042 fixedVal = attVal;
1043 else
1044 error("<attribute>:fixed and default cannot occur together");
1045 }
1046 else if ("use" == attName) {
1047 if (attVal == "required")
1048 use = true;
1049 else
1050 use = false;
1051 }
1052 else {
1053 int n=-1;
1054 if(!attNs.empty() && ((n=checkImport(attNs))!=-1)){
1055 fixedVal=attNs;//hack for non schema attributes
1056 defaultVal=attVal;//store non schema attributes.esp for soapenc:arrayType
1057 }else{
1058 error("<attribute>:Unsupported attribute {"+ attNs+ "}:"+attName,2);
1059 }
1060 }
1061 }
1062 //Now parse the children of the attribute tag viz simpleType
1063 do
1064 {
1065 xParser_->nextTag();
1066 if (xParser_->getEventType() == xParser_->END_TAG)
1067 {
1068 if (xParser_->getName() == "attribute")
1069 break;
1070
1071 //if an end tag is seen proceed till next start tag
1072 while (xParser_->getEventType() != xParser_->START_TAG)
1073 xParser_->nextTag();
1074 }
1075
1076 else if (xParser_->getName() == "simpleType")
1077 {
1078 XSDType *elemType = parseSimpleType();
1079
1080 //create an anonymous type
1081 type_id = typesTable_.addType(elemType);
1082 }
1083
1084 else if (xParser_->getName() == "annotation")
1085 parseAnnotation();
1086 else
1087 error("<attribute>:Syntax error or unkown tag "+xParser_->getName());
1088 }
1089 while (true);
1090
1091 Attribute a(name,
1092 type_id,
1093 qualified,
1094 defaultVal,
1095 fixedVal,
1096 use);
1097 return a;
1098
1099}
1100
1101SimpleType *
1102SchemaParser::parseSimpleType()
1103{
1104 SimpleType *st = new SimpleType(tnsUri_);
1105 int basetype_id = 0;
1106 int attcnt;
1107 attcnt = xParser_->getAttributeCount();
1108 for (int i = 0; i < attcnt; i++)
1109 {
1110 if ("name" == xParser_->getAttributeName(i))
1111 st->setName(xParser_->getAttributeValue(i));
1112
1113 else
1114 error("<simpleType> :" + xParser_->getAttributeName(i) +
1115 ":Unknown/Unsupported attribute ",2);
1116 }
1117
1118 do
1119 {
1120 xParser_->nextTag();
1121 if (xParser_->getEventType() == xParser_->END_TAG)
1122 {
1123 if (xParser_->getName() == "simpleType")
1124 break;
1125
1126 //if an end tag is seen proceed till next start tag
1127 while (xParser_->getEventType() != xParser_->START_TAG)
1128 xParser_->nextTag();
1129 }
1130 if (xParser_->getName() == "restriction")
1131 {
1132 attcnt = xParser_->getAttributeCount();
1133 for (int i = 0; i < attcnt; i++)
1134 {
1135 if ("base" == xParser_->getAttributeName(i))
1136 {
1137 Qname typeName(xParser_->getAttributeValue(i));
1138 typeName.setNamespace(xParser_->
1139 getNamespace(typeName.
1140 getPrefix()));
1141 st->setBaseType(basetype_id =
1142 getTypeId(typeName, true));
1143 if (basetype_id == 0)
1144 error("<simpleType>:" +
1145 xParser_->getAttributeValue(i) +
1146 ":Unknown base type ",1);
1147 }
1148 else
1149 error("<simpleType>:" + xParser_->getAttributeName(i) +
1150 ":Unknown/Unsupported attribute for <restriction>",2);
1151 }
1152 parseRestriction(st);
1153 }
1154 else if (xParser_->getName() == "union"){
1155
1156 std::string members = xParser_->getAttributeValue("", "memberTypes");
1157 size_t s = 0;
1158 while(s < members.length()){
1159 while(members[s]==' ')s++;
1160 std::string type = members.substr(s,members.find(' ',s)-s);
1161 Qname typeName(type);
1162 typeName.setNamespace(xParser_->getNamespace(typeName.getPrefix()));
1163 basetype_id = getTypeId(typeName,true);
1164 st->setUnionType(basetype_id);
1165 s+=type.length()+1;
1166 }
1167
1168 xParser_->nextTag();
1169 while(xParser_->getName() == "simpleType"){
1170 XSDType * t = parseSimpleType();
1171 Schema::Type i = (Schema::Type)typesTable_.addType(t);
1172
1173 st->setUnionType(i);
1174 xParser_->nextTag();
1175 }
1176 }
1177 else if(xParser_->getName() == "list"){
1178
1179 basetype_id = getTypeId(xParser_->getAttributeValue("", "itemType"));
1180 st->setListType(basetype_id);
1181 xParser_->nextTag();
1182 }
1183 else if (xParser_->getName() == "annotation")
1184 parseAnnotation();
1185 else
1186 error("<simpleType>:Syntax error");
1187 }
1188 while (true);
1189 return st;
1190}
1191
1192void
1193SchemaParser::parseRestriction(SimpleType * st,
1194 ComplexType * ct)
1195{
1196 if (st->getBaseTypeId() == 0)
1197 error("<restriction>:unkown BaseType",1);
1198
1199 do {
1200 xParser_->nextTag();
1201 if (xParser_->getEventType() == xParser_->END_TAG)
1202 {
1203 if (xParser_->getName() == "restriction")
1204 break;
1205 else
1206 xParser_->nextTag();
1207 if (xParser_->getName() == "restriction"
1208 && xParser_->getEventType() == xParser_->END_TAG)
1209 break;
1210 }
1211 while (xParser_->getName() == "annotation") {
1212 parseAnnotation();
1213 xParser_->nextTag();
1214 }
1215 if(xParser_->getName()=="attribute" && ct!=0){
1216 bool f=false;
1217 Attribute a=parseAttribute(f);
1218 ct->addAttribute(a,f);
1219 }
1220 else if (st->isvalidFacet(xParser_->getName())){
1221 //This function also sets the facet if valid
1222
1223 st->setFacetValue(xParser_->getName(),
1224 xParser_->getAttributeValue("", "value"));
1225 }else{
1226 error("<restriction>:" + xParser_->getName() +
1227 " is not a valid facet /attribute for the type",1);
1228 }
1229 } while (true);
1230}
1231
1232void
1233SchemaParser::parseComplexContent(ComplexType * ct)
1234{
1235 int attcnt = xParser_->getAttributeCount();
1236 int i = 0;
1237 Qname typeName;
1238
1239 ct->setContentModel(Schema::Complex);
1240 xParser_->nextTag();
1241
1242 while (xParser_->getName() == "annotation") {
1243 parseAnnotation();
1244 xParser_->nextTag();
1245 }
1246
1247 if (xParser_->getName() == "restriction") {
1248 attcnt = xParser_->getAttributeCount();
1249 for (i = 0; i < attcnt; i++) {
1250 if ("base" == xParser_->getAttributeName(i))
1251 {
1252 typeName = xParser_->getAttributeValue(i);
1253 typeName.setNamespace(xParser_->
1254 getNamespace(typeName.getPrefix()));
1255 }
1256 }
1257 ct->setBaseType(getTypeId(typeName, true),
1259 }
1260 else if (xParser_->getName() == "extension") {
1261 attcnt = xParser_->getAttributeCount();
1262 for (i = 0; i < attcnt; i++) {
1263 if ("base" == xParser_->getAttributeName(i)) {
1264 typeName = xParser_->getAttributeValue(i);
1265 typeName.setNamespace(xParser_->
1266 getNamespace(typeName.getPrefix()));
1267 }
1268 }
1269 ct->setBaseType(getTypeId(typeName, true),
1271 }
1272
1273 xParser_->nextTag();
1274 while (xParser_->getName() == "annotation") {
1275 parseAnnotation();
1276 xParser_->nextTag();
1277 }
1278
1279 {
1280 std::string elemName=xParser_->getName();
1281 ContentModel * cm=0;
1282 if (elemName == "all"){
1283 cm= new ContentModel(Schema::All);
1284 }
1285 else if (elemName == "sequence"){
1286 cm= new ContentModel(Schema::Sequence);
1287 }
1288 else if (elemName == "choice"){
1289 cm= new ContentModel(Schema::Choice);
1290 }
1291
1292 if(cm){
1293 parseContent(cm);
1294 ct->setContents(cm);
1295 xParser_->nextTag();
1296 }
1297
1298 //parse any attributes
1299 while (xParser_->getEventType() != xParser_->END_TAG){
1300
1301 if (xParser_->getName() == "attribute") {
1302 bool f=false;
1303 Attribute a=parseAttribute(f);
1304 ct->addAttribute(a,f);
1305 }
1306 else if(xParser_->getName() == "attributeGroup")
1307 {
1308 parseAttributeGroup(ct);
1309
1310 }
1311 else if (xParser_->getName() == "anyAttribute")
1312 addAnyAttribute(ct);
1313
1314 xParser_->nextTag();
1315 }
1316 }
1317
1318 do {
1319 if (xParser_->getEventType() == xParser_->END_TAG)
1320 if ((xParser_->getName() == "restriction" ||
1321 xParser_->getName() == "extension") )
1322 break;
1323 xParser_->nextTag();
1324 }
1325 while (true);
1326
1327 xParser_->nextTag();
1328}
1329
1330
1331void
1332SchemaParser::parseSimpleContent(ComplexType * ct)
1333{
1334 ct->setContentModel(Schema::Simple);
1335 xParser_->nextTag();
1336 if (xParser_->getName() == "restriction")
1337 {
1338 SimpleType *st = new SimpleType(tnsUri_);
1339 int attcnt = xParser_->getAttributeCount();
1340 int basetype_id = 0;
1341 for (int i = 0; i < attcnt; i++)
1342 {
1343 if ("base" == xParser_->getAttributeName(i))
1344 {
1345 Qname typeName(xParser_->getAttributeValue(i));
1346 typeName.setNamespace(xParser_->
1347 getNamespace(typeName.getPrefix()));
1348 st->setBaseType(basetype_id = getTypeId(typeName, true));
1349 if (basetype_id == 0)
1350 error("<simpleContent> :" +
1351 xParser_->getAttributeValue(i) +
1352 ":Unknown base type ",1);
1353 }
1354
1355 else
1356 error("<simpleContent> :" + xParser_->getAttributeName(i) +
1357 ":Unknown/Unsupported attribute ",2);
1358 }
1359 parseRestriction(st,ct);
1360 int typeId = typesTable_.addType(st);
1361 ct->setSimpleContentType(typeId);
1362 }
1363
1364 else if (xParser_->getName() == "extension")
1365 {
1366 //This extension does not use the full model that can come in
1367 //ComplexContent .It uses the simple model.no particle allowed ,only attributes
1368 int attcnt = xParser_->getAttributeCount();
1369 int basetype_id = 0;
1370 for (int i = 0; i < attcnt; i++)
1371 {
1372 if ("base" == xParser_->getAttributeName(i))
1373 {
1374 Qname typeName(xParser_->getAttributeValue(i));
1375 typeName.setNamespace(xParser_->
1376 getNamespace(typeName.getPrefix()));
1377 ct->setSimpleContentType(basetype_id =
1378 getTypeId(typeName, true));
1379 if (basetype_id == 0)
1380 error("<simpleContent> :" +
1381 xParser_->getAttributeValue(i) +
1382 ":Unknown base type ",1);
1383 }
1384
1385 else
1386 error("<simpleContent> :" + xParser_->getAttributeName(i) +
1387 ":Unknown/Unsupported attribute ");
1388 }
1389 xParser_->nextTag();
1390 do
1391 {
1392
1393 if (xParser_->getName() == "attribute")
1394 {
1395 bool f=false;
1396 Attribute a=parseAttribute(f);
1397 ct->addAttribute(a,f);
1398
1399
1400 }
1401 else if(xParser_->getName() == "attributeGroup")
1402 {
1403 parseAttributeGroup(ct);
1404
1405 }
1406
1407 else if (xParser_->getName() == "anyAttribute")
1408 addAnyAttribute(ct);
1409 else
1410 break;
1411 xParser_->nextTag();
1412 }while(true);
1413
1414 if (!
1415 (xParser_->getName() == "extension"
1416 && xParser_->getEventType() == xParser_->END_TAG))
1417 error("<simpleContent> :Syntax error :extension");
1418 }
1419 xParser_->nextTag();
1420 if (!
1421 (xParser_->getName() == "simpleContent"
1422 && xParser_->getEventType() == xParser_->END_TAG))
1423 error("<simpleContent> :Syntax error ");
1424}
1425
1426
1427bool
1428SchemaParser::parseRedefine()
1429{
1430 parseInclude();
1431 resolveFwdRefs_=false;
1432 parseSchema("redefine");
1433 resolveFwdRefs_=true;
1434 return true;
1435}
1436
1437bool
1438SchemaParser::parseInclude()
1439{
1440 ifstream xsdStream;
1441 std::string loc = xParser_->getAttributeValue("", "schemaLocation");
1442
1443
1444 // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases
1445 //in the the test. Will not work for paths like "C:\temp\schema.xsd" .Use the file:/ protocol
1446
1447
1448 if ( loc.find("/",0) != 0 && // not an asolute path
1449 loc.find("file:/",0) == std::string::npos &&
1450 loc.find("http://") == std::string::npos)
1451 loc = uri_ + loc;
1452
1453
1454#ifndef _WIN32
1455
1456 if (!loc.empty()) {
1457
1458 std::string schemaconf= confPath_ + "schema.conf";
1459 try {
1460 ConfigFile cf(schemaconf);
1461 cf.readInto<std::string>(loc,loc);
1462 }catch (const ConfigFile::file_not_found & e) {}
1463 }
1464#endif
1465
1466
1467 if(!loc.empty())
1468 {
1469 if(XmlUtils::fetchUri(loc,fname_))
1470 {
1471 /*
1472 * If the schema definition was retrieved successfully
1473 * process it and add all type definitions and
1474 * declaration to the current namespace
1475 */
1476 xsdStream.open(fname_.c_str());
1477
1478 XmlPullParser * xpp = new XmlPullParser(xsdStream);
1479 XmlPullParser * tmpXparser=xParser_;
1480 xParser_=xpp;
1481
1482 xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true);
1483 xParser_->require(XmlPullParser::START_DOCUMENT, "", "");
1484 while (xParser_->getEventType() != xParser_->END_DOCUMENT){
1485 xParser_->nextTag();
1486 if (xParser_->getEventType() == xParser_->START_TAG &&
1487 xParser_->getName() == "schema"){
1488 resolveFwdRefs_=false;
1489
1490 if(!parseSchemaTag())
1491 error("Error while parsing the included schema " + loc);
1492 else{
1493
1494 resolveFwdRefs_=true;
1495 break;
1496 }
1497 }
1498 }
1499 xParser_=tmpXparser;
1500 delete xpp;
1501 }
1502 else{
1503
1504 error("Error while opening the included schema " + loc);
1505 }
1506 }
1507 else{
1508
1509 error("schemaLocation is a required attribute for <include>");
1510 }
1511
1512 xParser_->nextTag();
1513 return true;
1514}
1515
1516bool
1517SchemaParser::parseImport()
1518{
1519 Qname typeName;
1520 std::string xsdFile;
1521 std::string ns = xParser_->getAttributeValue("", "namespace");
1522 std::string loc=xParser_->getAttributeValue("", "schemaLocation");
1523
1524 if(ns == tnsUri_)
1525 return parseInclude();//sometimes import is used to import schemas in same ns.
1526 //treat it internally like include
1527
1528
1529 // if (loc.empty())
1530 // loc = ns; //try using the namespace as schemalocation
1531
1532
1533// if ( !loc.empty() && loc.find("http://") == std::string::npos)
1534// loc = uri_ + loc;
1535
1536 if ( !loc.empty() &&
1537 loc.find("/",0) != 0 && // no an asolute path
1538 loc.find("file:/",0) == std::string::npos &&
1539 loc.find("http://") == std::string::npos)
1540 loc = uri_ + loc;
1541
1542#ifndef _WIN32
1543 if (!loc.empty()) {
1544
1545 std::string schemaconf= confPath_ + "schema.conf";
1546 try {
1547 ConfigFile cf(schemaconf);
1548 cf.readInto<std::string>(loc,loc);
1549 }catch (const ConfigFile::file_not_found &e) {}
1550 }
1551#endif
1552
1553 if(!loc.empty())
1554 {
1555 if(XmlUtils::fetchUri(loc,xsdFile))
1556 {
1557 /*
1558 * If the schema definition was retrieved successfully
1559 * process it and add it to list of imported schemas
1560 */
1561 SchemaParser *sp = new SchemaParser(xsdFile,ns);
1562 sp->setUri(uri_);
1563 //pass the imports to the new schema parser
1564 for (size_t i = 0; i < importedSchemas_.size(); i++) {
1565
1566 if(importedSchemas_[i].sParser ) {
1567 sp->addImport(importedSchemas_[i].sParser);
1568 }
1569 }
1570
1571
1572
1573 if(sp->parseSchemaTag())
1574 addImport(sp);
1575 else
1576 error("Error while parsing imported namespace "+ns,0);
1577
1578 }
1579 else{
1580
1581 error("could not import namespace from location "+loc);
1582 }
1583 }
1584 else{
1585 // if no location is mentioned ,just add the namespace,types will be resolved later
1586
1587 addImport(ns);
1588 }
1589
1590 error("Imported namespace "+ns+" from " + loc,2);
1591
1592 if (loc.empty())
1593 error("No location supplied for the import"+ns,2);
1594
1595 xParser_->nextTag();
1596 return true;
1597}
1598
1599bool SchemaParser::isBasicType(int sType) const
1600{
1601 if (sType > Schema::XSD_ANYURI || sType <= Schema::XSD_INVALID)
1602 return false;
1603
1604 else
1605 return true;
1606}
1607
1608
1609//This function gets the id of a type whose Qname is passed.
1610//The Qname struct if it has a prefix must either be a valid namespace
1611//default is http://www.w3.org/2001/XMLSchema
1612//This function has two modes
1613//if 'create' is true a new type is created (for fwd references)
1614//otherwise the existing list of parsed types is used for resolution
1615
1616int
1617SchemaParser::getTypeId( const Qname & type, bool create)
1618{
1619 std::string typens = type.getNamespace();
1620 if (typens.empty()||
1621 typens == tnsUri_ ||
1622 typens == Schema::SchemaUri){
1623
1624 return typesTable_.getTypeId(type, create);
1625 }
1626 else {
1627 //postpone resolution till matchExtRefs is called
1628 if (importedSchemas_.size() == 0 && create) {
1629
1630 return typesTable_.addExternalTypeId(type, 0);
1631 }
1632
1633 //search in the array of imported schemas
1634 int typeId = 0;
1635 for (size_t i = 0; i < importedSchemas_.size(); i++) {
1636
1637 if ( importedSchemas_[i].ns == type.getNamespace()) {
1638
1639 if(importedSchemas_[i].sParser ) {
1640
1641 typeId = importedSchemas_[i].sParser->getTypeId(type, false);
1642 //get the type definition from the imported namespace schema parser and
1643 // add a reference to the current schema parser
1644 if (typeId) {
1645 return typesTable_.addExternalTypeId(type,
1646 (XSDType *) importedSchemas_[i].sParser->getType(typeId));
1647 }
1648 else
1649 return 0;
1650 }
1651 }
1652 }
1653 if (create){
1654 //automatically add an unreferenced namespace as an import
1655 addImport(type.getNamespace());
1656 return typesTable_.addExternalTypeId(type, 0);
1657 }
1658 }
1659 return XSD_INVALID;
1660}
1661
1662
1663//resolves any external references with the imported schemas
1664//This method must be called to ensure resolution of all types
1666{
1667 int unresolved=typesTable_.getNumExtRefs();
1668 if(unresolved > 0) {
1669 for (int i = 0; i < unresolved; i++){
1670
1671 Qname & type = typesTable_.getExtRefName(i);
1672 int localId = typesTable_.getExtRefType(i);
1673
1674 //search in the array of imported schemas
1675 int typeId = 0;
1676 for (size_t n = 0; n < importedSchemas_.size(); n++)
1677 {
1678 if (importedSchemas_[n].ns == type.getNamespace())
1679 {
1680 if(importedSchemas_[n].sParser){
1681 typeId = importedSchemas_[n].sParser->getTypeId(type);
1682 if (typeId != 0)
1683 typesTable_.addExtType((XSDType *) importedSchemas_[n].sParser->getType(typeId),
1684 localId);
1685 }
1686 }
1687 }
1688
1689 if (typeId == 0) {
1690
1691 logFile_<<"Undefined type "<<type<<std::endl;
1692 }
1693 }
1694 }
1695 if (typesTable_.detectUndefinedTypes())
1696 {
1697 typesTable_.printUndefinedTypes(logFile_);logFile_.flush();
1698 logFile_<<"Unresolved types in namespace "<<tnsUri_<<std::endl;
1699 return false;
1700 }
1701
1702 else{
1703
1704 return true;
1705 }
1706
1707}
1708
1709
1710//resolves any forward references of the kind<element ref=Qname... >
1711void
1712SchemaParser::resolveForwardElementRefs()
1713{
1714 bool errors=false;
1715 if (lForwardElemRefs_.empty())
1716 return;
1717 for (list < Qname >::iterator pQnames = lForwardElemRefs_.begin();
1718 pQnames != lForwardElemRefs_.end(); pQnames++) {
1719
1720 // cout<<*pQnames<<std::endl;
1721 Element *e = const_cast<Element*>(getElement(*pQnames));
1722 //TODO , in case the forward ref is in an imported schema we cant just copy the type id
1723 //it needs to be changed to make it a valid type id in current schema
1724 if (e)
1725 typesTable_.resolveForwardElementRefs(pQnames->getLocalName(),*e);
1726 else {
1727 error("Could not resolve element reference "+pQnames->getLocalName(),1);
1728 errors=true;
1729 }
1730 }
1731 if(errors)
1732 error("Unresolved element references",1);
1733}
1734
1735
1736void
1737SchemaParser::resolveForwardAttributeRefs()
1738{
1739 bool errors=false;
1740 if (lForwardAttributeRefs_.empty())
1741 return;
1742 for (list < Qname >::iterator pQnames = lForwardAttributeRefs_.begin();
1743 pQnames != lForwardAttributeRefs_.end(); pQnames++)
1744 {
1745 Attribute *a = getAttribute(*pQnames);
1746 if (a)
1747 typesTable_.resolveForwardAttributeRefs(pQnames-> getLocalName(), *a);
1748 else {
1749 error("Could not resolve attribute reference {"+pQnames->getNamespace()
1750 +"}"+pQnames->getLocalName(),1);
1751 errors=true;
1752 }
1753 }
1754 if(errors)
1755 error("Unresolved attributes references");
1756}
1757
1758
1759//get the element id of a globally declared element
1760const Element*
1761SchemaParser::getElement(const Qname & element,bool checkImports)const
1762{
1763 std::string typens = element.getNamespace();
1764 if (typens.empty())
1765 typens = tnsUri_;
1766 if (typens== tnsUri_ || typens == Schema::SchemaUri)
1767 {
1768 int i = 0;
1769 //check if it is a global element
1770 for (std::list<Element>::const_iterator eli=lElems_.begin();
1771 eli!= lElems_.end();
1772 eli++,i++)
1773 if (eli->getName() == element.getLocalName())
1774 return &(*eli);
1775 return 0;
1776 }
1777 else if (checkImports)
1778 { //search imported namespaces
1779 for (size_t i = 0; i < importedSchemas_.size(); i++)
1780 {
1781 if ( importedSchemas_[i].ns == typens)
1782 {
1783 if(importedSchemas_[i].sParser )
1784 {
1785 return importedSchemas_[i].sParser->getElement(element);
1786 }
1787 }
1788 }
1789 }
1790 return 0;
1791}
1792
1793//get the attribute id of a globally declared attribute
1794Attribute*
1796{
1797 std::string typens = attribute.getNamespace();
1798 if (typens.empty())
1799 typens = tnsUri_;
1800
1801 if (typens == tnsUri_ || typens == Schema::SchemaUri) {
1802 //check if it is a global attribute
1803 for(std::list<Attribute>::iterator ali=lAttributes_.begin();
1804 ali!=lAttributes_.end();
1805 ali++)
1806 if (ali->getName() == attribute.getLocalName())
1807 return &(*ali);
1808 }else {
1809 //search imported namespaces
1810 for (size_t i = 0; i < importedSchemas_.size(); i++)
1811 {
1812 if ( importedSchemas_[i].ns == typens)
1813 {
1814 if(importedSchemas_[i].sParser )
1815 {
1816 return importedSchemas_[i].sParser->getAttribute(attribute);
1817 }
1818 }
1819 }
1820 }
1821 return 0;
1822}
1823
1824//get the element id of a globally declared element
1825Group*
1827{
1828 std::string typens = name.getNamespace();
1829 if (typens.empty())
1830 typens = tnsUri_;
1831 if (typens== tnsUri_ || typens == Schema::SchemaUri)
1832 {
1833
1834 //check if it is a global group
1835 for (std::list<Group>::iterator gli =lGroups_.begin();
1836 gli!= lGroups_.end();
1837 gli++)
1838 if (gli->getName() == name.getLocalName())
1839 return &(*gli);
1840 return 0;
1841 }
1842 else
1843 { //search imported namespaces
1844 for (size_t i = 0; i < importedSchemas_.size(); i++)
1845 {
1846 if ( importedSchemas_[i].ns == typens)
1847 {
1848 if(importedSchemas_[i].sParser )
1849 {
1850 return importedSchemas_[i].sParser->getGroup(name);
1851 }
1852 }
1853 }
1854 }
1855 return 0;
1856}
1857
1860{
1861 std::string typens = name.getNamespace();
1862 if (typens.empty())
1863 typens = tnsUri_;
1864 if (typens== tnsUri_ || typens == Schema::SchemaUri)
1865 {
1866
1867 //check if it is a global group
1868 for (AttributeGroupList::iterator agli = lAttributeGroups_.begin();
1869 agli!= lAttributeGroups_.end();
1870 agli++)
1871 if ((*agli)->getName() == name.getLocalName())
1872 return (*agli);
1873 return 0;
1874 }
1875 else
1876 { //search imported namespaces
1877 for (size_t i = 0; i < importedSchemas_.size(); i++)
1878 {
1879 if ( importedSchemas_[i].ns == typens)
1880 {
1881 if(importedSchemas_[i].sParser )
1882 {
1883 return importedSchemas_[i].sParser->getAttributeGroup(name);
1884 }
1885 }
1886 }
1887 }
1888 return 0;
1889}
1890
1891std::string
1893{
1894 return tnsUri_;
1895}
1896
1897
1898const XSDType *
1900{
1901 return (const XSDType *) typesTable_.getTypePtr(id);
1902}
1903
1904
1905const XSDType *
1906SchemaParser::getType(const Qname & type,bool checkImports )
1907{
1908 int id;
1909 Qname t=type;
1910
1911 if((id=getTypeId(t,false))==0)
1912 return 0;
1913 else {
1914 const XSDType* pType = (const XSDType *) typesTable_.getTypePtr(id);
1915 if (!checkImports) {
1916
1917 if(pType->getNamespace() != tnsUri_)
1918 return 0;
1919
1920 }
1921 return pType;
1922 }
1923}
1924
1925
1926 const XSDType *
1927 SchemaParser::getType(int id, std::string &nameSpace)
1928 {
1929 const SchemaParser *sp = getImportedSchema(nameSpace);
1930 if (sp == NULL)
1931 {
1932 return 0;
1933 }
1934 else
1935 {
1936 return sp->getType(id);
1937 }
1938 }
1939
1940 const SchemaParser *
1941 SchemaParser::getImportedSchema(std::string &nameSpace)
1942 {
1943 if (nameSpace.empty()|| nameSpace == tnsUri_ || nameSpace == Schema::SchemaUri)
1944 {
1945 return this;
1946 }
1947
1948 for (size_t i = 0; i < importedSchemas_.size(); i++)
1949 {
1950 if ( importedSchemas_[i].ns == nameSpace)
1951 {
1952 return importedSchemas_[i].sParser;
1953 }
1954 }
1955 return NULL;
1956 }
1957
1958list < const XSDType *>*
1960{
1961 list < const XSDType *>*pLTypes = new list < const XSDType * >;
1962 for (int i = 0; i < getNumTypes(); i++)
1963 {
1964 const XSDType *pType = getType(i + Schema::XSD_ANYURI + 1);
1965 pLTypes->push_back(pType);
1966 }
1967 return pLTypes;
1968}
1969
1970
1971int
1973{
1974 return typesTable_.getNumTypes();
1975}
1976
1977
1978int
1980{
1981 return lElems_.size();
1982}
1983
1984
1985int
1987{
1988 return lAttributes_.size();
1989}
1990
1991//To be deprecated
1992bool
1993SchemaParser::addImports(const std::vector<SchemaParser *> & schemaParsers)
1994{
1995 for (size_t i=0;i<schemaParsers.size() ;i++){
1996
1997 if(schemaParsers[i]->getNamespace()!=tnsUri_){
1998
1999 addImport(schemaParsers[i]);
2000 }
2001 }
2002 return true;
2003}
2004
2005bool
2007{
2008 //check if the namespace is added in the import list
2009 int i= checkImport(sp->getNamespace());
2010 // std::cout<<"Copying imports to "<<sp->tnsUri_<<std::endl;
2011 // sp->copyImports(this);
2012 if(i>=0) {
2013 importedSchemas_[i].sParser=sp;
2014 importedSchemas_[i].ns=sp->getNamespace();
2015 }
2016 else {
2017 //if this was a new import increment
2018 ImportedSchema imp;
2019 imp.sParser=sp;
2020 imp.ns=sp->getNamespace();
2021 importedSchemas_.push_back(imp);
2022 }
2023 return true;
2024}
2025
2026void
2027SchemaParser::copyImports(SchemaParser * sp)
2028{
2029 for(size_t i=0;i<importedSchemas_.size();i++) {
2030
2031 if (importedSchemas_[i].sParser)
2032 sp->addImport(importedSchemas_[i].sParser);
2033 }
2034}
2035
2036int
2037SchemaParser::checkImport(std::string nsp)const
2038{
2039 for(size_t i=0;i<importedSchemas_.size();i++)
2040 {
2041 if(importedSchemas_[i].ns==nsp)
2042 return i;
2043 }
2044 return -1;
2045}
2046
2047bool
2049 std::string location)
2050{
2051
2052 int i= checkImport(ns);
2053 if(i==-1) {
2054 ImportedSchema imp;
2055 imp.sParser=0;
2056 imp.ns=ns;
2057 importedSchemas_.push_back(imp);
2058 i =importedSchemas_.size()-1;
2059 }else {
2060 return true;
2061 }
2062
2063 if(location.empty())
2064 return true;
2065 std::string xsdFile;
2066 if(XmlUtils::fetchUri(location,xsdFile))
2067 {
2068 /*
2069 * If the schema definition was retrieved successfully
2070 * process it and add it to list of imported schemas
2071 */
2072 SchemaParser *sp = new SchemaParser(xsdFile,ns);
2073 sp->setUri(uri_);
2074 if(sp->parseSchemaTag())
2075 {
2076 importedSchemas_[i].sParser=sp;
2077 return true;
2078 }
2079 else return false;
2080 }
2081 else return false;
2082
2083}
2084
2085
2086void SchemaParser::error(std::string mesg, int level)
2087{
2088
2089 if (level == 0) {
2090
2091 SchemaParserException spe(mesg + "\nFatal Error in SchemaParser\n");
2092 spe.line = xParser_->getLineNumber();
2093 spe.col = xParser_->getColumnNumber();
2094 throw spe;
2095 }
2096
2097 else if (level_ >=1 && level == 1){
2098
2099 logFile_ << "Error @" << xParser_->
2100 getLineNumber() << ":" << xParser_->
2101 getColumnNumber() << XmlUtils::dbsp << mesg << endl;
2102 }
2103 else if (level_ >= 2 && level == 2) {
2104
2105 logFile_ << "Alert @" << xParser_->
2106 getLineNumber() << ":" << xParser_->
2107 getColumnNumber() << XmlUtils::dbsp << mesg << endl;
2108
2109 }
2110}
2111
2112
2113int
2115{
2116 const XSDType *pType = getType(typeId);
2117 int id = typeId;
2118 if (pType != 0) {
2119
2120 /*
2121 It could be a complex type with
2122 simple content or a schema defined simpleType
2123 */
2124 if (pType->isSimple() == false){
2125
2126 const ComplexType * cType= static_cast<const ComplexType*> (pType);
2127
2128 if(cType->getContentModel()==Schema::Simple){
2129
2130 id = cType->getContentType();
2131 }
2132 else {
2133
2134 return Schema::XSD_INVALID;
2135 }
2136 }
2137 else{
2138
2139 id = (static_cast<const SimpleType *>(pType))->getBaseTypeId();
2140 }
2141 id = getBasicContentType(id);
2142 }
2143 return id;
2144}
2145
2146std::string
2148{
2149 if (isBasicType(t)){
2150 return typesTable_.getAtomicTypeName(t);
2151 }
2152 else {
2153 const XSDType * pType = (const XSDType *) typesTable_.getTypePtr(t);
2154 if (pType)
2155 return pType->getName();
2156 }
2157 return "";
2158}
2159
2160
2161//handle soap arrays .this is really a special case.more like a hack
2162bool
2163SchemaParser::makeListFromSoapArray (ComplexType * ct)
2164{
2165 const XSDType * baseType=getType(ct->getBaseTypeId());
2166 if (baseType) {
2167 if(baseType->getNamespace()== "http://schemas.xmlsoap.org/soap/encoding/" &&
2168 baseType->getName()=="Array"){
2169
2170 const Attribute* a = ct->getAttribute("arrayType");
2171 if (!a)
2172 return false;
2173
2174 std::string array = a->defaultVal();
2175 Qname q(array);
2176 array = q.getLocalName();
2177 while (array[array.length()-1] ==']' &&
2178 array[array.length()-2] =='[')
2179 array = array.substr(0,array.length()-2);
2180
2181 std::string arrayNs = xParser_->getNamespace(q.getPrefix());
2182 q = Qname(array);
2183 q.setNamespace(arrayNs);
2184 Schema::Type t = (Schema::Type)getTypeId(q,true);
2185 Element e("*",tnsUri_,tnsUri_,t,0,UNBOUNDED);
2186 if (ct->getContents() == 0){
2188 ct->setContents(cm);
2189 }
2190 ct->getContents()->addElement(e);
2191 return true;
2192 }
2193 }
2194 return false;
2195}
2196}
#define UNBOUNDED
Definition: Element.h:29
#define FEATURE_PROCESS_NAMESPACES
Definition: XmlPullParser.h:40
Definition: Qname.h:31
std::string getLocalName(void) const
Definition: Qname.h:76
void setNamespace(std::string uri)
Definition: Qname.h:97
std::string getPrefix(void) const
Definition: Qname.h:83
std::string getNamespace(void) const
Definition: Qname.h:90
std::string defaultVal() const
Definition: Attribute.h:104
ContentModel * getContents() const
Definition: ComplexType.h:155
void setContents(ContentModel *ct)
Definition: ComplexType.h:163
const Attribute * getAttribute(const std::string &name) const
Definition: ComplexType.cpp:80
int getContentType() const
Definition: ComplexType.h:104
void addElement(const Element &e)
std::string getNamespace(void) const
Group * getGroup(const Qname &name)
SchemaParser(const std::string &Uri, std::string tns="", std::ostream &log=std::cout, const std::string &confPath="")
int getBasicContentType(int typeId) const
void setUri(const std::string &u)
Definition: SchemaParser.h:447
bool addImports(const std::vector< SchemaParser * > &schemaParsers)
std::string getTypeName(Schema::Type t) const
Attribute * getAttribute(const Qname &attribute)
int getNumElements() const
int getNumAttributes() const
const SchemaParser * getImportedSchema(std::string &nameSpace)
const XSDType * getType(const Qname &type, bool checkImports=true)
const Element * getElement(const Qname &element, bool checkImports=true) const
ConstTypeList * getAllTypes() const
int getTypeId(const Qname &, bool create=false)
bool addImport(std::string ns, std::string location="")
AttributeGroup * getAttributeGroup(const Qname &name)
bool isBasicType(int sType) const
std::string getAtomicTypeName(Schema::Type t) const
Definition: TypesTable.cpp:73
bool detectUndefinedTypes(void)
Definition: TypesTable.cpp:299
int getNumTypes(void) const
Definition: TypesTable.h:77
void resolveForwardElementRefs(const std::string &name, Element &e)
Definition: TypesTable.cpp:309
void setTargetNamespace(std::string Uri)
Definition: TypesTable.h:82
int addExtType(XSDType *type, int id)
Definition: TypesTable.cpp:215
XSDType * getTypePtr(int id) const
Definition: TypesTable.cpp:350
Qname & getExtRefName(int index)
Definition: TypesTable.h:59
int addExternalTypeId(const Qname &type, const XSDType *pType)
Definition: TypesTable.cpp:196
int getExtRefType(int index)
Definition: TypesTable.h:63
int addType(XSDType *type)
Definition: TypesTable.cpp:103
int getTypeId(const Qname &name, bool create=false)
Definition: TypesTable.cpp:151
void printUndefinedTypes(std::ostream &out)
Definition: TypesTable.cpp:339
void resolveForwardAttributeRefs(const std::string &name, Attribute &a)
Definition: TypesTable.cpp:324
std::string getNamespace() const
Definition: XSDType.h:236
int getBaseTypeId() const
Definition: XSDType.h:185
std::string getName() const
Definition: XSDType.h:148
virtual bool isSimple() const =0
Schema::ContentModelType getContentModel() const
Definition: XSDType.h:164
void require(int type, std::string ns, std::string name)
int getColumnNumber()
Definition: XmlPullParser.h:68
int getLineNumber()
Definition: XmlPullParser.h:64
std::string getName()
Definition: XmlPullParser.h:79
std::string getNamespace(std::string prefix)
std::string getAttributeValue(int index)
std::string getNamespaceUri(int pos)
std::string getAttributeNamespace(int index)
int getNamespaceCount(int depth)
std::string getAttributeName(int index)
std::string getNamespacePrefix(int pos)
int getAttributeCount()
Definition: XmlPullParser.h:88
void setFeature(std::string feature, bool value)
ConstraintType
Definition: Schema.h:51
@ Keyref
Definition: Schema.h:54
@ Key
Definition: Schema.h:53
@ Unique
Definition: Schema.h:55
@ Sequence
Definition: Schema.h:33
@ Choice
Definition: Schema.h:34
@ All
Definition: Schema.h:35
@ Extension
Definition: Schema.h:40
@ Restriction
Definition: Schema.h:39
const std::string SchemaUri
Definition: Schema.h:92
@ Mixed
Definition: Schema.h:48
@ Simple
Definition: Schema.h:46
@ Complex
Definition: Schema.h:47
Type
Definition: Schema.h:60
@ XSD_INVALID
Definition: Schema.h:61
@ XSD_ANYTYPE
Definition: Schema.h:88
@ XSD_SCHEMA
Definition: Schema.h:62
@ XSD_ANY
Definition: Schema.h:87
@ XSD_ANYURI
Definition: Schema.h:89
int parseInt(std::string s, int radix=10)
Definition: XmlUtils.cpp:70
bool WSDLPULL_EXPORT fetchUri(std::string uri, std::string &path)
Definition: XmlUtils.cpp:293
std::ostream & dbsp(std::ostream &str)
Definition: XmlUtils.cpp:103