wsdlpull 1.23
Loading...
Searching...
No Matches
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 //if an end tag is seen proceed till next start tag
843 while (xParser_->getEventType() != xParser_->START_TAG)
844 xParser_->nextTag();
845 }
846 if(elemName=="selector"){
847 c->setSelector(xParser_->getAttributeValue("", "xpath"));
848 xParser_->nextTag();
849 }
850 else if(elemName=="field"){
851 c->addField(xParser_->getAttributeValue("", "xpath"));
852 xParser_->nextTag();
853 }
854 }while (true);
855 return c;
856}
857
858
859Element
860SchemaParser::addAny(ContentModel* cm)
861{
862 std::string ns;
863
864 int type_id = Schema::XSD_ANY, minimum = 1, maximum = 1, attcnt;
865 //note processContents=lax .
866 attcnt = xParser_->getAttributeCount();
867 for (int i = 0; i < attcnt; i++)
868 {
869 std::string attr = xParser_->getAttributeName(i);
870 if ("namespace" == attr)
871 ns = xParser_->getAttributeValue(i);
872
873 else if ("minOccurs" == attr)
874 minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
875
876 else if ("maxOccurs" == attr)
877 {
878 if ("unbounded" == xParser_->getAttributeValue(i))
879 maximum = UNBOUNDED;
880 else
881 maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10);
882 if (maximum == -1){ //invalid value for maxOccurs
883 error("<element>:Invalid value for maxOccurs",1);
884 maximum=1;
885 }
886 }
887
888 else if ("processContents" == attr || "id" == attr) {
889
890 //do nothing
891 }
892 else
893 error("<any>:Unsupported Attribute "+attr,2);
894 }
895
896 xParser_->nextTag();
897 do
898 {
899 if (xParser_->getEventType() == xParser_->END_TAG)
900 {
901 if (xParser_->getName() == "any")
902 break;
903
904 }
905 xParser_->nextToken();
906 }while (true);
907
908
909 Element e(ns,
910 ns,
911 ns,
912 type_id,
913 minimum,
914 maximum);
915
916 cm->addElement(e);
917 return e;
918}
919
920
921Attribute
922SchemaParser::addAnyAttribute(ComplexType * cType)
923{
924 std::string ns;
925 int type_id = Schema::XSD_ANY,attcnt;
926 bool qualified = true;
927
928 //note processContents=lax .
929 attcnt = xParser_->getAttributeCount();
930 for (int i = 0; i < attcnt; i++)
931 {
932 std::string attr = xParser_->getAttributeName(i);
933 if ("namespace" == attr)
934 ns = xParser_->getAttributeValue(i);
935
936 else if ("processContents" == attr || "id" == attr)
937 {
938
939 //do nothing
940 }
941 else
942 error("<anyAttribute>:Unsupported Attribute "+attr,1);
943 }
944
945 Attribute a(ns,
946 type_id,
947 qualified);
948 if(cType)
949 cType->addAttribute(a);
950 xParser_->nextTag();
951 while (xParser_->getName() == "annotation")
952 {
953 parseAnnotation();
954 xParser_->nextTag();
955 }
956 return a;
957
958}
959
960
961//This function parses and attribute
962Attribute
963SchemaParser::parseAttribute(bool & fwdRef)
964{
965 std::string name, fixedVal, defaultVal;
966 int type_id = 0, attcnt;
967 bool qualified = false, use = false;
968 fwdRef=false;
969
970 Qname refAttribute;
971 attcnt = xParser_->getAttributeCount();
972 for (int i = 0; i < attcnt; i++) {
973 std::string attName = xParser_->getAttributeName(i);
974 std::string attNs=xParser_->getAttributeNamespace(i);
975 std::string attVal=xParser_->getAttributeValue(i);
976
977
978 if ("name" == attName)
979 name = attVal;
980 else if ("type" == attName) {
981 if (type_id > 0)
982 error("<attribute>:type and ref are mutually exclusive in element decl");
983 Qname typeName(attVal);
984 typeName.setNamespace(xParser_->
985 getNamespace(typeName.getPrefix()));
986 type_id = getTypeId(typeName, true);
987 if (type_id == 0)
988 error("<attribute>:Could not resolve type " +
989 typeName.getNamespace() +
990 ":" +typeName.getLocalName(),1);
991 }
992 else if ("form" == attName) {
993 if ("qualified" == attVal)
994 qualified = true;
995 else
996 qualified = false;
997 }
998 else if ("ref" == attName) {
999 if (!name.empty())
1000 error("<attribute>:name and ref are mutually exclusive in element decl");
1001 if (type_id > 0)
1002 error("<attribute>:type and ref are mutually exclusive in element decl");
1003 refAttribute = attVal;
1004 refAttribute.setNamespace(xParser_->getNamespace(refAttribute.getPrefix()));
1005 Attribute *a =0;
1006 if(refAttribute.getNamespace()==tnsUri_){
1007 a=getAttribute(refAttribute);
1008 }else{
1009 int i=checkImport(refAttribute.getNamespace());
1010 if(i >=0 && importedSchemas_[i].sParser){
1011 a=importedSchemas_[i].sParser->getAttribute(refAttribute);
1012 }
1013 else
1014 a=0;
1015 }
1016
1017 if (a == 0){
1018 fwdRef = true;
1019 name=refAttribute.getLocalName();
1020 lForwardAttributeRefs_.push_back(refAttribute);
1021 }
1022 else{
1023 name = a->getName();
1024 type_id = a->getType();
1025 qualified = a->isQualified();
1026 if (defaultVal.empty())
1027 defaultVal = a->defaultVal();
1028 if (fixedVal.empty())
1029 fixedVal = a->fixedVal();
1030 }
1031 }
1032 else if ("default" == attName) {
1033 if (fixedVal.empty())
1034 defaultVal = attVal;
1035 else
1036 error
1037 ("<attribute>:fixed and default cannot occur together");
1038 }
1039 else if ("fixed" == attName) {
1040 if (defaultVal.empty())
1041 fixedVal = attVal;
1042 else
1043 error("<attribute>:fixed and default cannot occur together");
1044 }
1045 else if ("use" == attName) {
1046 if (attVal == "required")
1047 use = true;
1048 else
1049 use = false;
1050 }
1051 else {
1052 int n=-1;
1053 if(!attNs.empty() && ((n=checkImport(attNs))!=-1)){
1054 fixedVal=attNs;//hack for non schema attributes
1055 defaultVal=attVal;//store non schema attributes.esp for soapenc:arrayType
1056 }else{
1057 error("<attribute>:Unsupported attribute {"+ attNs+ "}:"+attName,2);
1058 }
1059 }
1060 }
1061 //Now parse the children of the attribute tag viz simpleType
1062 do
1063 {
1064 xParser_->nextTag();
1065 if (xParser_->getEventType() == xParser_->END_TAG)
1066 {
1067 if (xParser_->getName() == "attribute")
1068 break;
1069
1070 //if an end tag is seen proceed till next start tag
1071 while (xParser_->getEventType() != xParser_->START_TAG)
1072 xParser_->nextTag();
1073 }
1074
1075 else if (xParser_->getName() == "simpleType")
1076 {
1077 XSDType *elemType = parseSimpleType();
1078
1079 //create an anonymous type
1080 type_id = typesTable_.addType(elemType);
1081 }
1082
1083 else if (xParser_->getName() == "annotation")
1084 parseAnnotation();
1085 else
1086 error("<attribute>:Syntax error or unkown tag "+xParser_->getName());
1087 }
1088 while (true);
1089
1090 Attribute a(name,
1091 type_id,
1092 qualified,
1093 defaultVal,
1094 fixedVal,
1095 use);
1096 return a;
1097
1098}
1099
1100SimpleType *
1101SchemaParser::parseSimpleType()
1102{
1103 SimpleType *st = new SimpleType(tnsUri_);
1104 int basetype_id = 0;
1105 int attcnt;
1106 attcnt = xParser_->getAttributeCount();
1107 for (int i = 0; i < attcnt; i++)
1108 {
1109 if ("name" == xParser_->getAttributeName(i))
1110 st->setName(xParser_->getAttributeValue(i));
1111
1112 else
1113 error("<simpleType> :" + xParser_->getAttributeName(i) +
1114 ":Unknown/Unsupported attribute ",2);
1115 }
1116
1117 do
1118 {
1119 xParser_->nextTag();
1120 if (xParser_->getEventType() == xParser_->END_TAG)
1121 {
1122 if (xParser_->getName() == "simpleType")
1123 break;
1124
1125 //if an end tag is seen proceed till next start tag
1126 while (xParser_->getEventType() != xParser_->START_TAG)
1127 xParser_->nextTag();
1128 }
1129 if (xParser_->getName() == "restriction")
1130 {
1131 attcnt = xParser_->getAttributeCount();
1132 for (int i = 0; i < attcnt; i++)
1133 {
1134 if ("base" == xParser_->getAttributeName(i))
1135 {
1136 Qname typeName(xParser_->getAttributeValue(i));
1137 typeName.setNamespace(xParser_->
1138 getNamespace(typeName.
1139 getPrefix()));
1140 st->setBaseType(basetype_id =
1141 getTypeId(typeName, true));
1142 if (basetype_id == 0)
1143 error("<simpleType>:" +
1144 xParser_->getAttributeValue(i) +
1145 ":Unknown base type ",1);
1146 }
1147 else
1148 error("<simpleType>:" + xParser_->getAttributeName(i) +
1149 ":Unknown/Unsupported attribute for <restriction>",2);
1150 }
1151 parseRestriction(st);
1152 }
1153 else if (xParser_->getName() == "union"){
1154
1155 std::string members = xParser_->getAttributeValue("", "memberTypes");
1156 size_t s = 0;
1157 while(s < members.length()){
1158 while(members[s]==' ')s++;
1159 std::string type = members.substr(s,members.find(' ',s)-s);
1160 Qname typeName(type);
1161 typeName.setNamespace(xParser_->getNamespace(typeName.getPrefix()));
1162 basetype_id = getTypeId(typeName,true);
1163 st->setUnionType(basetype_id);
1164 s+=type.length()+1;
1165 }
1166
1167 xParser_->nextTag();
1168 while(xParser_->getName() == "simpleType"){
1169 XSDType * t = parseSimpleType();
1170 Schema::Type i = (Schema::Type)typesTable_.addType(t);
1171
1172 st->setUnionType(i);
1173 xParser_->nextTag();
1174 }
1175 }
1176 else if(xParser_->getName() == "list"){
1177
1178 basetype_id = getTypeId(xParser_->getAttributeValue("", "itemType"));
1179 st->setListType(basetype_id);
1180 xParser_->nextTag();
1181 }
1182 else if (xParser_->getName() == "annotation")
1183 parseAnnotation();
1184 else
1185 error("<simpleType>:Syntax error");
1186 }
1187 while (true);
1188 return st;
1189}
1190
1191void
1192SchemaParser::parseRestriction(SimpleType * st,
1193 ComplexType * ct)
1194{
1195 if (st->getBaseTypeId() == 0)
1196 error("<restriction>:unkown BaseType",1);
1197
1198 do {
1199 xParser_->nextTag();
1200 if (xParser_->getEventType() == xParser_->END_TAG)
1201 {
1202 if (xParser_->getName() == "restriction")
1203 break;
1204 else
1205 xParser_->nextTag();
1206 if (xParser_->getName() == "restriction"
1207 && xParser_->getEventType() == xParser_->END_TAG)
1208 break;
1209 }
1210 while (xParser_->getName() == "annotation") {
1211 parseAnnotation();
1212 xParser_->nextTag();
1213 }
1214 if(xParser_->getName()=="attribute" && ct!=0){
1215 bool f=false;
1216 Attribute a=parseAttribute(f);
1217 ct->addAttribute(a,f);
1218 }
1219 else if (st->isvalidFacet(xParser_->getName())){
1220 //This function also sets the facet if valid
1221
1222 st->setFacetValue(xParser_->getName(),
1223 xParser_->getAttributeValue("", "value"));
1224 }else{
1225 error("<restriction>:" + xParser_->getName() +
1226 " is not a valid facet /attribute for the type",1);
1227 }
1228 } while (true);
1229}
1230
1231void
1232SchemaParser::parseComplexContent(ComplexType * ct)
1233{
1234 int attcnt = xParser_->getAttributeCount();
1235 int i = 0;
1236 Qname typeName;
1237
1238 ct->setContentModel(Schema::Complex);
1239 xParser_->nextTag();
1240
1241 while (xParser_->getName() == "annotation") {
1242 parseAnnotation();
1243 xParser_->nextTag();
1244 }
1245
1246 if (xParser_->getName() == "restriction") {
1247 attcnt = xParser_->getAttributeCount();
1248 for (i = 0; i < attcnt; i++) {
1249 if ("base" == xParser_->getAttributeName(i))
1250 {
1251 typeName = xParser_->getAttributeValue(i);
1252 typeName.setNamespace(xParser_->
1253 getNamespace(typeName.getPrefix()));
1254 }
1255 }
1256 ct->setBaseType(getTypeId(typeName, true),
1258 }
1259 else if (xParser_->getName() == "extension") {
1260 attcnt = xParser_->getAttributeCount();
1261 for (i = 0; i < attcnt; i++) {
1262 if ("base" == xParser_->getAttributeName(i)) {
1263 typeName = xParser_->getAttributeValue(i);
1264 typeName.setNamespace(xParser_->
1265 getNamespace(typeName.getPrefix()));
1266 }
1267 }
1268 ct->setBaseType(getTypeId(typeName, true),
1270 }
1271
1272 xParser_->nextTag();
1273 while (xParser_->getName() == "annotation") {
1274 parseAnnotation();
1275 xParser_->nextTag();
1276 }
1277
1278 {
1279 std::string elemName=xParser_->getName();
1280 ContentModel * cm=0;
1281 if (elemName == "all"){
1282 cm= new ContentModel(Schema::All);
1283 }
1284 else if (elemName == "sequence"){
1285 cm= new ContentModel(Schema::Sequence);
1286 }
1287 else if (elemName == "choice"){
1288 cm= new ContentModel(Schema::Choice);
1289 }
1290
1291 if(cm){
1292 parseContent(cm);
1293 ct->setContents(cm);
1294 xParser_->nextTag();
1295 }
1296
1297 //parse any attributes
1298 while (xParser_->getEventType() != xParser_->END_TAG){
1299
1300 if (xParser_->getName() == "attribute") {
1301 bool f=false;
1302 Attribute a=parseAttribute(f);
1303 ct->addAttribute(a,f);
1304 }
1305 else if(xParser_->getName() == "attributeGroup")
1306 {
1307 parseAttributeGroup(ct);
1308
1309 }
1310 else if (xParser_->getName() == "anyAttribute")
1311 addAnyAttribute(ct);
1312
1313 xParser_->nextTag();
1314 }
1315 }
1316
1317 do {
1318 if (xParser_->getEventType() == xParser_->END_TAG)
1319 if ((xParser_->getName() == "restriction" ||
1320 xParser_->getName() == "extension") )
1321 break;
1322 xParser_->nextTag();
1323 }
1324 while (true);
1325
1326 xParser_->nextTag();
1327}
1328
1329
1330void
1331SchemaParser::parseSimpleContent(ComplexType * ct)
1332{
1333 ct->setContentModel(Schema::Simple);
1334 xParser_->nextTag();
1335 if (xParser_->getName() == "restriction")
1336 {
1337 SimpleType *st = new SimpleType(tnsUri_);
1338 int attcnt = xParser_->getAttributeCount();
1339 int basetype_id = 0;
1340 for (int i = 0; i < attcnt; i++)
1341 {
1342 if ("base" == xParser_->getAttributeName(i))
1343 {
1344 Qname typeName(xParser_->getAttributeValue(i));
1345 typeName.setNamespace(xParser_->
1346 getNamespace(typeName.getPrefix()));
1347 st->setBaseType(basetype_id = getTypeId(typeName, true));
1348 if (basetype_id == 0)
1349 error("<simpleContent> :" +
1350 xParser_->getAttributeValue(i) +
1351 ":Unknown base type ",1);
1352 }
1353
1354 else
1355 error("<simpleContent> :" + xParser_->getAttributeName(i) +
1356 ":Unknown/Unsupported attribute ",2);
1357 }
1358 parseRestriction(st,ct);
1359 int typeId = typesTable_.addType(st);
1360 ct->setSimpleContentType(typeId);
1361 }
1362
1363 else if (xParser_->getName() == "extension")
1364 {
1365 //This extension does not use the full model that can come in
1366 //ComplexContent .It uses the simple model.no particle allowed ,only attributes
1367 int attcnt = xParser_->getAttributeCount();
1368 int basetype_id = 0;
1369 for (int i = 0; i < attcnt; i++)
1370 {
1371 if ("base" == xParser_->getAttributeName(i))
1372 {
1373 Qname typeName(xParser_->getAttributeValue(i));
1374 typeName.setNamespace(xParser_->
1375 getNamespace(typeName.getPrefix()));
1376 ct->setSimpleContentType(basetype_id =
1377 getTypeId(typeName, true));
1378 if (basetype_id == 0)
1379 error("<simpleContent> :" +
1380 xParser_->getAttributeValue(i) +
1381 ":Unknown base type ",1);
1382 }
1383
1384 else
1385 error("<simpleContent> :" + xParser_->getAttributeName(i) +
1386 ":Unknown/Unsupported attribute ");
1387 }
1388 xParser_->nextTag();
1389 do
1390 {
1391
1392 if (xParser_->getName() == "attribute")
1393 {
1394 bool f=false;
1395 Attribute a=parseAttribute(f);
1396 ct->addAttribute(a,f);
1397
1398
1399 }
1400 else if(xParser_->getName() == "attributeGroup")
1401 {
1402 parseAttributeGroup(ct);
1403
1404 }
1405
1406 else if (xParser_->getName() == "anyAttribute")
1407 addAnyAttribute(ct);
1408 else
1409 break;
1410 xParser_->nextTag();
1411 }while(true);
1412
1413 if (!
1414 (xParser_->getName() == "extension"
1415 && xParser_->getEventType() == xParser_->END_TAG))
1416 error("<simpleContent> :Syntax error :extension");
1417 }
1418 xParser_->nextTag();
1419 if (!
1420 (xParser_->getName() == "simpleContent"
1421 && xParser_->getEventType() == xParser_->END_TAG))
1422 error("<simpleContent> :Syntax error ");
1423}
1424
1425
1426bool
1427SchemaParser::parseRedefine()
1428{
1429 parseInclude();
1430 resolveFwdRefs_=false;
1431 parseSchema("redefine");
1432 resolveFwdRefs_=true;
1433 return true;
1434}
1435
1436bool
1437SchemaParser::parseInclude()
1438{
1439 ifstream xsdStream;
1440 std::string loc = xParser_->getAttributeValue("", "schemaLocation");
1441
1442
1443 // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases
1444 //in the the test. Will not work for paths like "C:\temp\schema.xsd" .Use the file:/ protocol
1445
1446
1447 if ( loc.find("/",0) != 0 && // not an asolute path
1448 loc.find("file:/",0) == std::string::npos &&
1449 loc.find("http://") == std::string::npos)
1450 loc = uri_ + loc;
1451
1452
1453#ifndef _WIN32
1454
1455 if (!loc.empty()) {
1456
1457 std::string schemaconf= confPath_ + "schema.conf";
1458 try {
1459 ConfigFile cf(schemaconf);
1460 cf.readInto<std::string>(loc,loc);
1461 }catch (const ConfigFile::file_not_found & e) {}
1462 }
1463#endif
1464
1465
1466 if(!loc.empty())
1467 {
1468 if(XmlUtils::fetchUri(loc,fname_))
1469 {
1470 /*
1471 * If the schema definition was retrieved successfully
1472 * process it and add all type definitions and
1473 * declaration to the current namespace
1474 */
1475 xsdStream.open(fname_.c_str());
1476
1477 XmlPullParser * xpp = new XmlPullParser(xsdStream);
1478 XmlPullParser * tmpXparser=xParser_;
1479 xParser_=xpp;
1480
1481 xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true);
1482 xParser_->require(XmlPullParser::START_DOCUMENT, "", "");
1483 while (xParser_->getEventType() != xParser_->END_DOCUMENT){
1484 xParser_->nextTag();
1485 if (xParser_->getEventType() == xParser_->START_TAG &&
1486 xParser_->getName() == "schema"){
1487 resolveFwdRefs_=false;
1488
1489 if(!parseSchemaTag())
1490 error("Error while parsing the included schema " + loc);
1491 else{
1492
1493 resolveFwdRefs_=true;
1494 break;
1495 }
1496 }
1497 }
1498 xParser_=tmpXparser;
1499 delete xpp;
1500 }
1501 else{
1502
1503 error("Error while opening the included schema " + loc);
1504 }
1505 }
1506 else{
1507
1508 error("schemaLocation is a required attribute for <include>");
1509 }
1510
1511 xParser_->nextTag();
1512 return true;
1513}
1514
1515bool
1516SchemaParser::parseImport()
1517{
1518 Qname typeName;
1519 std::string xsdFile;
1520 std::string ns = xParser_->getAttributeValue("", "namespace");
1521 std::string loc=xParser_->getAttributeValue("", "schemaLocation");
1522
1523 if(ns == tnsUri_)
1524 return parseInclude();//sometimes import is used to import schemas in same ns.
1525 //treat it internally like include
1526
1527 // if (loc.empty())
1528 // loc = ns; //try using the namespace as schemalocation
1529
1530 // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases in the the test
1531// if ( !loc.empty() && loc.find("http://") == std::string::npos)
1532// loc = uri_ + loc;
1533
1534 if ( !loc.empty() &&
1535 loc.find("/",0) != 0 && // no an asolute path
1536 loc.find("file:/",0) == std::string::npos &&
1537 loc.find("http://") == std::string::npos)
1538 loc = uri_ + loc;
1539
1540#ifndef _WIN32
1541 if (!loc.empty()) {
1542
1543 std::string schemaconf= confPath_ + "schema.conf";
1544 try {
1545 ConfigFile cf(schemaconf);
1546 cf.readInto<std::string>(loc,loc);
1547 }catch (const ConfigFile::file_not_found &e) {}
1548 }
1549#endif
1550
1551 if(!loc.empty())
1552 {
1553 if(XmlUtils::fetchUri(loc,xsdFile))
1554 {
1555 /*
1556 * If the schema definition was retrieved successfully
1557 * process it and add it to list of imported schemas
1558 */
1559 SchemaParser *sp = new SchemaParser(xsdFile,ns);
1560 sp->setUri(uri_);
1561 //pass the imports to the new schema parser
1562 for (size_t i = 0; i < importedSchemas_.size(); i++) {
1563
1564 if(importedSchemas_[i].sParser ) {
1565 sp->addImport(importedSchemas_[i].sParser);
1566 }
1567 }
1568
1569 if(sp->parseSchemaTag())
1570 addImport(sp);
1571 else
1572 error("Error while parsing imported namespace "+ns,0);
1573
1574 }
1575 else{
1576
1577 error("could not import namespace from location "+loc);
1578 }
1579 }
1580 else{
1581 // if no location is mentioned ,just add the namespace,types will be resolved later
1582
1583 addImport(ns);
1584 }
1585
1586 error("Imported namespace "+ns+" from " + loc,2);
1587
1588 if (loc.empty())
1589 error("No location supplied for the import"+ns,2);
1590
1591 xParser_->nextTag();
1592 return true;
1593}
1594
1595bool SchemaParser::isBasicType(int sType) const
1596{
1597 if (sType > Schema::XSD_ANYURI || sType <= Schema::XSD_INVALID)
1598 return false;
1599
1600 else
1601 return true;
1602}
1603
1604
1605//This function gets the id of a type whose Qname is passed.
1606//The Qname struct if it has a prefix must either be a valid namespace
1607//default is http://www.w3.org/2001/XMLSchema
1608//This function has two modes
1609//if 'create' is true a new type is created (for fwd references)
1610//otherwise the existing list of parsed types is used for resolution
1611
1612int
1613SchemaParser::getTypeId( const Qname & type, bool create)
1614{
1615 std::string typens = type.getNamespace();
1616 if (typens.empty()||
1617 typens == tnsUri_ ||
1618 typens == Schema::SchemaUri){
1619
1620 return typesTable_.getTypeId(type, create);
1621 }
1622 else {
1623 //postpone resolution till matchExtRefs is called
1624 if (importedSchemas_.size() == 0 && create) {
1625
1626 return typesTable_.addExternalTypeId(type, 0);
1627 }
1628
1629 //search in the array of imported schemas
1630 int typeId = 0;
1631 for (size_t i = 0; i < importedSchemas_.size(); i++) {
1632
1633 if ( importedSchemas_[i].ns == type.getNamespace()) {
1634
1635 if(importedSchemas_[i].sParser ) {
1636
1637 typeId = importedSchemas_[i].sParser->getTypeId(type, false);
1638 //get the type definition from the imported namespace schema parser and
1639 // add a reference to the current schema parser
1640 if (typeId) {
1641 return typesTable_.addExternalTypeId(type,
1642 (XSDType *) importedSchemas_[i].sParser->getType(typeId));
1643 }
1644 else
1645 return 0;
1646 }
1647 }
1648 }
1649 if (create){
1650 //automatically add an unreferenced namespace as an import
1651 addImport(type.getNamespace());
1652 return typesTable_.addExternalTypeId(type, 0);
1653 }
1654 }
1655 return XSD_INVALID;
1656}
1657
1658
1659//resolves any external references with the imported schemas
1660//This method must be called to ensure resolution of all types
1662{
1663 int unresolved=typesTable_.getNumExtRefs();
1664 if(unresolved > 0) {
1665 for (int i = 0; i < unresolved; i++){
1666
1667 Qname & type = typesTable_.getExtRefName(i);
1668 int localId = typesTable_.getExtRefType(i);
1669
1670 //search in the array of imported schemas
1671 int typeId = 0;
1672 for (size_t n = 0; n < importedSchemas_.size(); n++)
1673 {
1674 if (importedSchemas_[n].ns == type.getNamespace())
1675 {
1676 if(importedSchemas_[n].sParser){
1677 typeId = importedSchemas_[n].sParser->getTypeId(type);
1678 if (typeId != 0)
1679 typesTable_.addExtType((XSDType *) importedSchemas_[n].sParser->getType(typeId),
1680 localId);
1681 }
1682 }
1683 }
1684
1685 if (typeId == 0) {
1686
1687 logFile_<<"Undefined type "<<type<<std::endl;
1688 }
1689 }
1690 }
1691 if (typesTable_.detectUndefinedTypes())
1692 {
1693 typesTable_.printUndefinedTypes(logFile_);logFile_.flush();
1694 logFile_<<"Unresolved types in namespace "<<tnsUri_<<std::endl;
1695 return false;
1696 }
1697
1698 else{
1699
1700 return true;
1701 }
1702
1703}
1704
1705
1706//resolves any forward references of the kind<element ref=Qname... >
1707void
1708SchemaParser::resolveForwardElementRefs()
1709{
1710 bool errors=false;
1711 if (lForwardElemRefs_.empty())
1712 return;
1713 for (list < Qname >::iterator pQnames = lForwardElemRefs_.begin();
1714 pQnames != lForwardElemRefs_.end(); pQnames++) {
1715
1716 // cout<<*pQnames<<std::endl;
1717 Element *e = const_cast<Element*>(getElement(*pQnames));
1718 //TODO , in case the forward ref is in an imported schema we cant just copy the type id
1719 //it needs to be changed to make it a valid type id in current schema
1720 if (e)
1721 typesTable_.resolveForwardElementRefs(pQnames->getLocalName(),*e);
1722 else {
1723 error("Could not resolve element reference "+pQnames->getLocalName(),1);
1724 errors=true;
1725 }
1726 }
1727 if(errors)
1728 error("Unresolved element references",1);
1729}
1730
1731
1732void
1733SchemaParser::resolveForwardAttributeRefs()
1734{
1735 bool errors=false;
1736 if (lForwardAttributeRefs_.empty())
1737 return;
1738 for (list < Qname >::iterator pQnames = lForwardAttributeRefs_.begin();
1739 pQnames != lForwardAttributeRefs_.end(); pQnames++)
1740 {
1741 Attribute *a = getAttribute(*pQnames);
1742 if (a)
1743 typesTable_.resolveForwardAttributeRefs(pQnames-> getLocalName(), *a);
1744 else {
1745 error("Could not resolve attribute reference {"+pQnames->getNamespace()
1746 +"}"+pQnames->getLocalName(),1);
1747 errors=true;
1748 }
1749 }
1750 if(errors)
1751 error("Unresolved attributes references");
1752}
1753
1754
1755//get the element id of a globally declared element
1756const Element*
1757SchemaParser::getElement(const Qname & element,bool checkImports)const
1758{
1759 std::string typens = element.getNamespace();
1760 if (typens.empty())
1761 typens = tnsUri_;
1762 if (typens== tnsUri_ || typens == Schema::SchemaUri)
1763 {
1764 int i = 0;
1765 //check if it is a global element
1766 for (std::list<Element>::const_iterator eli=lElems_.begin();
1767 eli!= lElems_.end();
1768 eli++,i++)
1769 if (eli->getName() == element.getLocalName())
1770 return &(*eli);
1771 return 0;
1772 }
1773 else if (checkImports)
1774 { //search imported namespaces
1775 for (size_t i = 0; i < importedSchemas_.size(); i++)
1776 {
1777 if ( importedSchemas_[i].ns == typens)
1778 {
1779 if(importedSchemas_[i].sParser )
1780 {
1781 return importedSchemas_[i].sParser->getElement(element);
1782 }
1783 }
1784 }
1785 }
1786 return 0;
1787}
1788
1789//get the attribute id of a globally declared attribute
1790Attribute*
1792{
1793 std::string typens = attribute.getNamespace();
1794 if (typens.empty())
1795 typens = tnsUri_;
1796
1797 if (typens == tnsUri_ || typens == Schema::SchemaUri) {
1798 //check if it is a global attribute
1799 for(std::list<Attribute>::iterator ali=lAttributes_.begin();
1800 ali!=lAttributes_.end();
1801 ali++)
1802 if (ali->getName() == attribute.getLocalName())
1803 return &(*ali);
1804 }else {
1805 //search imported namespaces
1806 for (size_t i = 0; i < importedSchemas_.size(); i++)
1807 {
1808 if ( importedSchemas_[i].ns == typens)
1809 {
1810 if(importedSchemas_[i].sParser )
1811 {
1812 return importedSchemas_[i].sParser->getAttribute(attribute);
1813 }
1814 }
1815 }
1816 }
1817 return 0;
1818}
1819
1820//get the element id of a globally declared element
1821Group*
1823{
1824 std::string typens = name.getNamespace();
1825 if (typens.empty())
1826 typens = tnsUri_;
1827 if (typens== tnsUri_ || typens == Schema::SchemaUri)
1828 {
1829
1830 //check if it is a global group
1831 for (std::list<Group>::iterator gli =lGroups_.begin();
1832 gli!= lGroups_.end();
1833 gli++)
1834 if (gli->getName() == name.getLocalName())
1835 return &(*gli);
1836 return 0;
1837 }
1838 else
1839 { //search imported namespaces
1840 for (size_t i = 0; i < importedSchemas_.size(); i++)
1841 {
1842 if ( importedSchemas_[i].ns == typens)
1843 {
1844 if(importedSchemas_[i].sParser )
1845 {
1846 return importedSchemas_[i].sParser->getGroup(name);
1847 }
1848 }
1849 }
1850 }
1851 return 0;
1852}
1853
1856{
1857 std::string typens = name.getNamespace();
1858 if (typens.empty())
1859 typens = tnsUri_;
1860 if (typens== tnsUri_ || typens == Schema::SchemaUri)
1861 {
1862
1863 //check if it is a global group
1864 for (AttributeGroupList::iterator agli = lAttributeGroups_.begin();
1865 agli!= lAttributeGroups_.end();
1866 agli++)
1867 if ((*agli)->getName() == name.getLocalName())
1868 return (*agli);
1869 return 0;
1870 }
1871 else
1872 { //search imported namespaces
1873 for (size_t i = 0; i < importedSchemas_.size(); i++)
1874 {
1875 if ( importedSchemas_[i].ns == typens)
1876 {
1877 if(importedSchemas_[i].sParser )
1878 {
1879 return importedSchemas_[i].sParser->getAttributeGroup(name);
1880 }
1881 }
1882 }
1883 }
1884 return 0;
1885}
1886
1887std::string
1889{
1890 return tnsUri_;
1891}
1892
1893
1894const XSDType *
1896{
1897 return (const XSDType *) typesTable_.getTypePtr(id);
1898}
1899
1900
1901const XSDType *
1902SchemaParser::getType(const Qname & type,bool checkImports )
1903{
1904 int id;
1905 Qname t=type;
1906
1907 if((id=getTypeId(t,false))==0)
1908 return 0;
1909 else {
1910 const XSDType* pType = (const XSDType *) typesTable_.getTypePtr(id);
1911 if (!checkImports) {
1912
1913 if(pType->getNamespace() != tnsUri_)
1914 return 0;
1915
1916 }
1917 return pType;
1918 }
1919}
1920
1921
1922 const XSDType *
1923 SchemaParser::getType(int id, std::string &nameSpace)
1924 {
1925 const SchemaParser *sp = getImportedSchema(nameSpace);
1926 if (sp == NULL)
1927 {
1928 return 0;
1929 }
1930 else
1931 {
1932 return sp->getType(id);
1933 }
1934 }
1935
1936 const SchemaParser *
1937 SchemaParser::getImportedSchema(std::string &nameSpace)
1938 {
1939 if (nameSpace.empty()|| nameSpace == tnsUri_ || nameSpace == Schema::SchemaUri)
1940 {
1941 return this;
1942 }
1943
1944 for (size_t i = 0; i < importedSchemas_.size(); i++)
1945 {
1946 if ( importedSchemas_[i].ns == nameSpace)
1947 {
1948 return importedSchemas_[i].sParser;
1949 }
1950 }
1951 return NULL;
1952 }
1953
1954list < const XSDType *>*
1956{
1957 list < const XSDType *>*pLTypes = new list < const XSDType * >;
1958 for (int i = 0; i < getNumTypes(); i++)
1959 {
1960 const XSDType *pType = getType(i + Schema::XSD_ANYURI + 1);
1961 pLTypes->push_back(pType);
1962 }
1963 return pLTypes;
1964}
1965
1966
1967int
1969{
1970 return typesTable_.getNumTypes();
1971}
1972
1973
1974int
1976{
1977 return lElems_.size();
1978}
1979
1980
1981int
1983{
1984 return lAttributes_.size();
1985}
1986
1987//To be deprecated
1988bool
1989SchemaParser::addImports(const std::vector<SchemaParser *> & schemaParsers)
1990{
1991 for (size_t i=0;i<schemaParsers.size() ;i++){
1992
1993 if(schemaParsers[i]->getNamespace()!=tnsUri_){
1994
1995 addImport(schemaParsers[i]);
1996 }
1997 }
1998 return true;
1999}
2000
2001bool
2003{
2004 //check if the namespace is added in the import list
2005 int i= checkImport(sp->getNamespace());
2006 // std::cout<<"Copying imports to "<<sp->tnsUri_<<std::endl;
2007 // sp->copyImports(this);
2008 if(i>=0) {
2009 importedSchemas_[i].sParser=sp;
2010 importedSchemas_[i].ns=sp->getNamespace();
2011 }
2012 else {
2013 //if this was a new import increment
2014 ImportedSchema imp;
2015 imp.sParser=sp;
2016 imp.ns=sp->getNamespace();
2017 importedSchemas_.push_back(imp);
2018 }
2019 return true;
2020}
2021
2022void
2023SchemaParser::copyImports(SchemaParser * sp)
2024{
2025 for(size_t i=0;i<importedSchemas_.size();i++) {
2026
2027 if (importedSchemas_[i].sParser)
2028 sp->addImport(importedSchemas_[i].sParser);
2029 }
2030}
2031
2032int
2033SchemaParser::checkImport(std::string nsp)const
2034{
2035 for(size_t i=0;i<importedSchemas_.size();i++)
2036 {
2037 if(importedSchemas_[i].ns==nsp)
2038 return i;
2039 }
2040 return -1;
2041}
2042
2043bool
2045 std::string location)
2046{
2047
2048 int i= checkImport(ns);
2049 if(i==-1) {
2050 ImportedSchema imp;
2051 imp.sParser=0;
2052 imp.ns=ns;
2053 importedSchemas_.push_back(imp);
2054 i =importedSchemas_.size()-1;
2055 }else {
2056 return true;
2057 }
2058
2059 if(location.empty())
2060 return true;
2061 std::string xsdFile;
2062 if(XmlUtils::fetchUri(location,xsdFile))
2063 {
2064 /*
2065 * If the schema definition was retrieved successfully
2066 * process it and add it to list of imported schemas
2067 */
2068 SchemaParser *sp = new SchemaParser(xsdFile,ns);
2069 sp->setUri(uri_);
2070 if(sp->parseSchemaTag())
2071 {
2072 importedSchemas_[i].sParser=sp;
2073 return true;
2074 }
2075 else return false;
2076 }
2077 else return false;
2078
2079}
2080
2081
2082void SchemaParser::error(std::string mesg, int level)
2083{
2084
2085 if (level == 0) {
2086
2087 SchemaParserException spe(mesg + "\nFatal Error in SchemaParser\n");
2088 spe.line = xParser_->getLineNumber();
2089 spe.col = xParser_->getColumnNumber();
2090 throw spe;
2091 }
2092
2093 else if (level_ >=1 && level == 1){
2094
2095 logFile_ << "Error @" << xParser_->
2096 getLineNumber() << ":" << xParser_->
2097 getColumnNumber() << XmlUtils::dbsp << mesg << endl;
2098 }
2099 else if (level_ >= 2 && level == 2) {
2100
2101 logFile_ << "Alert @" << xParser_->
2102 getLineNumber() << ":" << xParser_->
2103 getColumnNumber() << XmlUtils::dbsp << mesg << endl;
2104
2105 }
2106}
2107
2108
2109int
2111{
2112 const XSDType *pType = getType(typeId);
2113 int id = typeId;
2114 if (pType != 0) {
2115
2116 /*
2117 It could be a complex type with
2118 simple content or a schema defined simpleType
2119 */
2120 if (pType->isSimple() == false){
2121
2122 const ComplexType * cType= static_cast<const ComplexType*> (pType);
2123
2124 if(cType->getContentModel()==Schema::Simple){
2125
2126 id = cType->getContentType();
2127 }
2128 else {
2129
2130 return Schema::XSD_INVALID;
2131 }
2132 }
2133 else{
2134
2135 id = (static_cast<const SimpleType *>(pType))->getBaseTypeId();
2136 }
2137 id = getBasicContentType(id);
2138 }
2139 return id;
2140}
2141
2142std::string
2144{
2145 if (isBasicType(t)){
2146 return typesTable_.getAtomicTypeName(t);
2147 }
2148 else {
2149 const XSDType * pType = (const XSDType *) typesTable_.getTypePtr(t);
2150 if (pType)
2151 return pType->getName();
2152 }
2153 return "";
2154}
2155
2156
2157//handle soap arrays .this is really a special case.more like a hack
2158bool
2159SchemaParser::makeListFromSoapArray (ComplexType * ct)
2160{
2161 const XSDType * baseType=getType(ct->getBaseTypeId());
2162 if (baseType) {
2163 if(baseType->getNamespace()== "http://schemas.xmlsoap.org/soap/encoding/" &&
2164 baseType->getName()=="Array"){
2165
2166 const Attribute* a = ct->getAttribute("arrayType");
2167 if (!a)
2168 return false;
2169
2170 std::string array = a->defaultVal();
2171 Qname q(array);
2172 array = q.getLocalName();
2173 while (array[array.length()-1] ==']' &&
2174 array[array.length()-2] =='[')
2175 array = array.substr(0,array.length()-2);
2176
2177 std::string arrayNs = xParser_->getNamespace(q.getPrefix());
2178 q = Qname(array);
2179 q.setNamespace(arrayNs);
2180 Schema::Type t = (Schema::Type)getTypeId(q,true);
2181 Element e("*",tnsUri_,tnsUri_,t,0,UNBOUNDED);
2182 if (ct->getContents() == 0){
2184 ct->setContents(cm);
2185 }
2186 ct->getContents()->addElement(e);
2187 return true;
2188 }
2189 }
2190 return false;
2191}
2192}
#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:57
bool WSDLPULL_EXPORT fetchUri(std::string uri, std::string &path)
Definition: XmlUtils.cpp:108
std::ostream & dbsp(std::ostream &str)
Definition: XmlUtils.cpp:90