wsdlpull
1.23
|
00001 /* 00002 * wsdlpull - A C++ parser for WSDL (Web services description language) 00003 * Copyright (C) 2005-2007 Vivek Krishna 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public 00015 * License along with this library; if not, write to the Free 00016 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 * 00018 * 00019 */ 00020 00021 #include "schemaparser/SchemaParser.h" 00022 00023 #ifndef _WIN32 00024 #include "xmlpull/ConfigFile.h" 00025 #endif 00026 00027 // 00028 #include <climits> 00029 00030 namespace Schema { 00031 using namespace std; 00032 SchemaParser::SchemaParser(XmlPullParser * parser, 00033 std::string tns, 00034 std::ostream & log, 00035 const std::string & s) 00036 :tnsUri_(tns), 00037 xParser_(parser), 00038 elementQualified_ (false), 00039 attributeQualified_ (false), 00040 deleteXmlParser_(false), 00041 resolveFwdRefs_(true), 00042 level_(1), 00043 logFile_(log), 00044 confPath_(s) 00045 { 00046 init(); 00047 } 00048 00049 SchemaParser::SchemaParser(const std::string &Uri, 00050 std::string tns , 00051 std::ostream & log , 00052 const std::string & s) 00053 :tnsUri_(tns), 00054 xParser_(0), 00055 elementQualified_ (false), 00056 attributeQualified_ (false), 00057 deleteXmlParser_(false), 00058 resolveFwdRefs_(true), 00059 level_(1), 00060 logFile_(log), 00061 confPath_(s) 00062 { 00063 if(XmlUtils::fetchUri(Uri,fname_)) 00064 { 00065 xmlStream_.open(fname_.c_str()); 00066 xParser_ = new XmlPullParser(xmlStream_); 00067 xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true); 00068 xParser_->require(XmlPullParser::START_DOCUMENT, "", ""); 00069 while (!xmlStream_.fail() && xParser_->getEventType() != xParser_->END_DOCUMENT) 00070 { 00071 xParser_->nextTag(); 00072 if (xParser_->getEventType() == xParser_->START_TAG && 00073 xParser_->getName() == "schema") 00074 { 00075 deleteXmlParser_=true; 00076 tnsUri_=tns; 00077 break; 00078 } 00079 } 00080 00081 } 00082 if(!deleteXmlParser_) //something wron while opening the schema file 00083 { 00084 delete xParser_; 00085 xParser_=0; 00086 } 00087 00088 init(); 00089 uri_ = Uri.substr(0,Uri.rfind('/') + 1); 00090 } 00091 00092 void 00093 SchemaParser::init() 00094 { 00095 lElems_.clear() ; 00096 lAttributes_.clear(); 00097 lAttributeGroups_.clear(); 00098 importedSchemas_.clear(); 00099 constraints_.clear(); 00100 00101 if (confPath_.empty()) { 00102 #if defined SCHEMADIR 00103 confPath_ = SCHEMADIR; 00104 #else 00105 confPath_ = "src/schemas"; 00106 #endif 00107 } 00108 00109 Element e("schema", 00110 SchemaUri, 00111 SchemaUri, 00112 Schema::XSD_SCHEMA); 00113 lElems_.push_back(e); 00114 00115 00116 00117 #ifdef LOGGING 00118 level_ = 2; 00119 #endif 00120 } 00121 00122 SchemaParser::~SchemaParser() 00123 { 00124 //clear the Types table 00125 typesTable_.clean(); 00126 if(deleteXmlParser_) { 00127 00128 delete xParser_; 00129 xmlStream_.close(); 00130 } 00131 00132 for (ConstraintList::iterator ci=constraints_.begin(); 00133 ci != constraints_.end(); 00134 ci++) 00135 delete *ci; 00136 for (AttributeGroupList::iterator agi = lAttributeGroups_.begin(); 00137 agi != lAttributeGroups_.end(); 00138 agi++) 00139 delete *agi; 00140 } 00141 00142 00143 /* 00144 * Parses an schema definition. 00145 * This is the main entry method for the schema parser 00146 */ 00147 bool 00148 SchemaParser::parseSchemaTag() 00149 { 00150 int i = 0; 00151 try { 00152 if(!xParser_) 00153 return false; 00154 while (xParser_->getEventType() != xParser_->START_TAG) 00155 xParser_->next(); 00156 xParser_->require(xParser_->START_TAG, Schema::SchemaUri, "schema"); 00157 int attcnt = xParser_->getAttributeCount(); 00158 00159 //parse the schema tag's attributes 00160 for (i = 0; i < attcnt; i++) { 00161 std::string attName = xParser_->getAttributeName(i); 00162 if ("targetNamespace" == attName) 00163 //store the tns URI 00164 tnsUri_ = xParser_->getAttributeValue(i); 00165 if ("version" == attName) 00166 version_ = xParser_->getAttributeValue(i); 00167 if ("elementFormDefault" == attName){ 00168 if (xParser_->getAttributeValue(i) == "unqualified") 00169 elementQualified_ = false; 00170 00171 else if (xParser_->getAttributeValue(i) == "qualified") 00172 elementQualified_ = true; 00173 } 00174 if ("attributeFormDefault" == attName) { 00175 if (xParser_->getAttributeValue(i) == "unqualified") 00176 attributeQualified_ = false; 00177 00178 else if (xParser_->getAttributeValue(i) == "qualified") 00179 attributeQualified_ = true; 00180 } 00181 } 00182 00183 for (i = xParser_->getNamespaceCount(xParser_->getDepth()) - 1; 00184 i > xParser_->getNamespaceCount(xParser_->getDepth() - 1) - 1; i--) 00185 if (xParser_->getNamespaceUri(i) == tnsUri_) 00186 tnsPrefix_ = xParser_->getNamespacePrefix(i); 00187 typesTable_.setTargetNamespace(tnsUri_); 00188 xParser_->nextTag(); 00189 00190 return parseSchema(); 00191 } catch (XmlPullParserException xpe){ 00192 00193 logFile_ <<"Error parsing schema for namespace "<<tnsUri_<<std::endl; 00194 logFile_ << xpe.description << " at " 00195 << xpe.line << ":" << xpe.col 00196 << std::endl; 00197 return false; 00198 } 00199 catch(SchemaParserException spe) { 00200 00201 spe.line = xParser_->getLineNumber(); 00202 spe.col = xParser_->getColumnNumber(); 00203 00204 logFile_ << spe.description << " at " 00205 << spe.line << ":" << spe.col 00206 << std::endl; 00207 00208 return false; 00209 } 00210 } 00211 00212 //this function handles the schema 00213 bool 00214 SchemaParser::parseSchema(std::string tag) 00215 { 00216 try 00217 { 00218 do 00219 { 00220 00221 if (xParser_->getEventType() == xParser_->END_TAG) 00222 { 00223 if (xParser_->getName() == tag) 00224 break; 00225 while (xParser_->getEventType() != xParser_->START_TAG) 00226 xParser_->nextTag(); 00227 } 00228 00229 /* 00230 This is the main loop 00231 Depending on the tag encountered call the appropriate routines 00232 Schema elements visible at this level 00233 1. Global Element declarations 00234 2. Global attribute declarations 00235 3. Complex type and Simple type declarations 00236 00237 */ 00238 std::string elemName = xParser_->getName(); 00239 if (elemName == "element") { 00240 bool fwd; 00241 Element e = parseElement(fwd); 00242 lElems_.push_back(e); 00243 } 00244 else if (elemName == "complexType") 00245 { 00246 XSDType *t = parseComplexType(); 00247 typesTable_.addType(t); 00248 } 00249 else if (elemName == "simpleType") 00250 { 00251 XSDType *t = parseSimpleType(); 00252 typesTable_.addType(t); 00253 } 00254 else if (elemName == "attribute") { 00255 bool fwd; 00256 lAttributes_.push_back(parseAttribute(fwd)); 00257 } 00258 else if (elemName == "annotation"){ 00259 parseAnnotation(); 00260 } 00261 else if (elemName == "import") { 00262 parseImport(); 00263 } 00264 else if (elemName=="include"){ 00265 parseInclude(); 00266 } 00267 else if(elemName=="attributeGroup") { 00268 AttributeGroup* ag = parseAttributeGroup(); 00269 if (ag) 00270 lAttributeGroups_.push_back(ag); 00271 00272 }else if(elemName=="group") { 00273 00274 lGroups_.push_back(parseGroup()); 00275 Group & g=lGroups_.back(); 00276 //make this grp the owner of the content model 00277 g.setContents(g.getContents(),false); 00278 } 00279 else if( elemName=="key") { 00280 00281 constraints_.push_back(parseConstraint(Schema::Key)); 00282 } 00283 else if( elemName=="keyref") { 00284 constraints_.push_back(parseConstraint(Schema::Keyref)); 00285 } 00286 else if( elemName=="unique") { 00287 constraints_.push_back(parseConstraint(Schema::Unique)); 00288 }else if (elemName=="redefine"){ 00289 parseRedefine(); 00290 } 00291 else { 00292 error("Unknown element "+ elemName,1); 00293 break; 00294 } 00295 xParser_->nextTag(); 00296 } 00297 while (true); 00298 if ((importedSchemas_.size() == 0) && 00299 typesTable_.detectUndefinedTypes()){ 00300 00301 typesTable_.printUndefinedTypes(logFile_);logFile_.flush(); 00302 error("Undefined Types in namespace "+tnsUri_); 00303 } 00304 if(shouldResolve()) 00305 { 00306 00307 resolveForwardElementRefs(); 00308 resolveForwardAttributeRefs(); 00309 } 00310 00311 } 00312 catch(SchemaParserException spe) 00313 { 00314 spe.line = xParser_->getLineNumber(); 00315 spe.col = xParser_->getColumnNumber(); 00316 00317 logFile_ << spe.description << " at " 00318 << spe.line << ":" << spe.col 00319 << std::endl; 00320 00321 return false; 00322 } 00323 return true; 00324 } 00325 00326 00327 void SchemaParser::parseAnnotation() 00328 { 00329 00330 do 00331 { 00332 xParser_->nextToken(); 00333 if (xParser_->getEventType() == xParser_->END_TAG 00334 && xParser_->getName() == "annotation") 00335 break; 00336 } 00337 while (true); 00338 } 00339 00340 00341 ComplexType * 00342 SchemaParser::parseComplexType() 00343 { 00344 ComplexType *newType = new ComplexType(tnsUri_); 00345 int attcnt = xParser_->getAttributeCount(); 00346 for (int i = 0; i < attcnt; i++) 00347 { 00348 if ("name" == xParser_->getAttributeName(i)) 00349 newType->setName(xParser_->getAttributeValue(i)); 00350 00351 if ("mixed" == xParser_->getAttributeName(i) && 00352 (xParser_->getAttributeValue(i).empty() || 00353 xParser_->getAttributeValue(i)=="true")) 00354 00355 newType->setContentModel(Schema::Mixed); 00356 } 00357 00358 00359 do 00360 { 00361 //begin parsing the complex type's children 00362 xParser_->nextTag(); 00363 if (xParser_->getEventType() == xParser_->END_TAG) 00364 { 00365 if (xParser_->getName() == "complexType") 00366 break; 00367 00368 //if an end tag is seen proceed till next start tag 00369 while (xParser_->getEventType() != xParser_->START_TAG) 00370 xParser_->nextTag(); 00371 } 00372 std::string elemName = xParser_->getName(); 00373 00374 00375 if (elemName == "all"){ 00376 ContentModel * cm= new ContentModel(Schema::All); 00377 newType->setContents(cm); 00378 parseContent(cm); 00379 } 00380 else if (elemName == "sequence"){ 00381 ContentModel * cm= new ContentModel(Schema::Sequence); 00382 newType->setContents(cm); 00383 parseContent(cm); 00384 } 00385 else if (elemName == "choice"){ 00386 ContentModel * cm= new ContentModel(Schema::Choice); 00387 newType->setContents(cm); 00388 parseContent(cm); 00389 } 00390 else if (elemName == "attribute") { 00391 bool f=false; 00392 Attribute a=parseAttribute(f); 00393 newType->addAttribute(a,f); 00394 }else if (elemName=="attributeGroup"){ 00395 parseAttributeGroup(newType); 00396 } 00397 else if (elemName=="group"){ 00398 //TODO 00399 ContentModel* cm= new ContentModel(Schema::Sequence); 00400 newType->setContents(cm); 00401 parseGroup(cm); 00402 } 00403 else if (elemName == "anyAttribute") 00404 addAnyAttribute(newType); 00405 00406 else if (elemName == "complexContent") 00407 parseComplexContent(newType); 00408 00409 else if (elemName == "simpleContent") 00410 parseSimpleContent(newType); 00411 00412 else if (xParser_->getName() == "annotation") 00413 parseAnnotation(); 00414 00415 else 00416 error("Unexpected tag: '"+elemName+"' in "+newType->getName() ); 00417 } 00418 while (true); 00419 makeListFromSoapArray(newType); 00420 return newType; 00421 } 00422 00423 AttributeGroup* 00424 SchemaParser::parseAttributeGroup(ComplexType* cType) 00425 { 00426 std::string name,ref; 00427 ref = xParser_->getAttributeValue("", "ref"); 00428 if (!ref.empty()) 00429 { 00430 Qname agRef(ref); 00431 AttributeGroup *ag= getAttributeGroup(agRef); 00432 if(cType && ag){ 00433 00434 for(list<Attribute>::iterator ai= ag->begin(); 00435 ai!=ag->end(); 00436 ai++) 00437 cType->addAttribute(*ai); 00438 } 00439 else if (cType){ 00440 cType->addAttributeGroupName(ref); 00441 } 00442 xParser_->nextTag(); 00443 return ag; 00444 } 00445 00446 name = xParser_->getAttributeValue("", "name"); 00447 AttributeGroup *ag = new AttributeGroup(name); 00448 xParser_->nextTag(); 00449 while (xParser_->getName() == "annotation") 00450 { 00451 parseAnnotation(); 00452 xParser_->nextTag(); 00453 } 00454 std::string elemName=xParser_->getName(); 00455 while (!((xParser_->getEventType() == xParser_->END_TAG) && 00456 (elemName == "attributeGroup"))){ 00457 00458 if(elemName=="attribute"){ 00459 bool fwd; 00460 ag->addAttribute(parseAttribute(fwd)); 00461 }else if(elemName=="attributeGroup"){ 00462 AttributeGroup* ag1=parseAttributeGroup(); 00463 for(list<Attribute>::iterator ai= ag1->begin(); 00464 ai!=ag1->end(); 00465 ai++) 00466 ag->addAttribute(*ai); 00467 }else if(elemName=="anyAttribute"){ 00468 ag->addAttribute(addAnyAttribute(cType)); 00469 } 00470 xParser_->nextTag(); 00471 elemName=xParser_->getName(); 00472 } 00473 00474 if(cType){ 00475 00476 for(list<Attribute>::iterator ai= ag->begin(); 00477 ai!=ag->end(); 00478 ai++) 00479 cType->addAttribute(*ai); 00480 delete ag;//dont store anonymous attribute groups 00481 ag = 0; 00482 } 00483 return ag; 00484 } 00485 00486 Group 00487 SchemaParser::parseGroup(ContentModel* c) 00488 { 00489 int minimum = 1, maximum = 1; 00490 std::string tmp, name,ref; 00491 00492 tmp = xParser_->getAttributeValue("", "minOccurs"); 00493 if (!tmp.empty()) 00494 minimum = XmlUtils::parseInt(tmp); 00495 tmp = xParser_->getAttributeValue("", "maxOccurs"); 00496 if (!tmp.empty()) { 00497 if ("unbounded" == tmp) 00498 maximum = UNBOUNDED; 00499 else 00500 maximum = XmlUtils::parseInt(tmp); 00501 } 00502 ref = xParser_->getAttributeValue("", "ref"); 00503 if (!ref.empty()) { 00504 00505 Qname gName(ref); 00506 xParser_->nextTag(); 00507 Group* gRef=getGroup(gName); 00508 if(gRef){ 00509 Group g(*gRef); 00510 if(c) 00511 c->addGroup(g,true); 00512 return g; 00513 } 00514 else{ 00515 Group g(gName.getLocalName(),minimum,maximum); 00516 if(c) 00517 c->addGroup(g,true); 00518 return g; 00519 } 00520 } 00521 00522 name = xParser_->getAttributeValue("", "name"); 00523 Group g(name,minimum,maximum); 00524 xParser_->nextTag(); 00525 while (xParser_->getName() == "annotation") { 00526 parseAnnotation(); 00527 xParser_->nextTag(); 00528 } 00529 00530 std::string elemName = xParser_->getName(); 00531 ContentModel * cm=0; 00532 if (elemName == "all"){ 00533 cm = new ContentModel(Schema::All); 00534 } 00535 else if (elemName == "sequence"){ 00536 cm= new ContentModel(Schema::Sequence); 00537 } 00538 else if (elemName == "choice"){ 00539 cm= new ContentModel(Schema::Choice); 00540 } 00541 g.setContents(cm,true); 00542 parseContent(cm); 00543 xParser_->nextTag(); 00544 00545 if(c) 00546 c->addGroup(g,false); 00547 return g; 00548 } 00549 00550 void 00551 SchemaParser::parseContent(ContentModel * cm) 00552 { 00553 int minimum = 1, maximum = 1; 00554 std::string tmp; 00555 00556 tmp = xParser_->getAttributeValue("", "minOccurs"); 00557 if (!tmp.empty()) 00558 minimum = XmlUtils::parseInt(tmp); 00559 tmp = xParser_->getAttributeValue("", "maxOccurs"); 00560 if (!tmp.empty()) 00561 { 00562 if ("unbounded" == tmp) 00563 maximum = UNBOUNDED; 00564 else 00565 maximum = XmlUtils::parseInt(tmp); 00566 } 00567 cm->setMin(minimum); 00568 cm->setMax(maximum); 00569 00570 xParser_->nextTag(); 00571 while (xParser_->getName() == "annotation") 00572 { 00573 parseAnnotation(); 00574 xParser_->nextTag(); 00575 } 00576 00577 while (!((xParser_->getEventType() == xParser_->END_TAG) && 00578 (xParser_->getName() == "choice" 00579 || xParser_->getName() == "sequence" 00580 || xParser_->getName() == "all"))) 00581 { 00582 if (xParser_->getName() == "element") { 00583 bool f=false; 00584 Element e =parseElement(f); 00585 cm->addElement(e); 00586 }else if(cm->getCompositor()!=Schema::All){ 00587 00588 if (xParser_->getName() == "any") 00589 addAny(cm); 00590 else if (xParser_->getName() == "choice"){ 00591 ContentModel * cmc= new ContentModel(Schema::Choice); 00592 cm->addContentModel(cmc); 00593 parseContent(cmc); 00594 } 00595 else if (xParser_->getName() == "sequence"){ 00596 ContentModel * cms= new ContentModel(Schema::Sequence); 00597 cm->addContentModel(cms); 00598 parseContent(cms); 00599 } 00600 else if (xParser_->getName() == "group"){ 00601 parseGroup(cm); 00602 } 00603 else if(xParser_->getName() == "annotation") { 00604 parseAnnotation(); 00605 } 00606 else 00607 error("parseContent: Unexpected tag "+xParser_->getName()); 00608 }else{ 00609 00610 error("parseContent <all>:Syntax Error"); 00611 } 00612 xParser_->nextTag(); 00613 } 00614 } 00615 00616 Element 00617 SchemaParser::parseElement(bool & fwdRef) 00618 { 00619 std::string name, fixedVal, defaultVal, 00620 // the namespace of the element is the 00621 // namespace of the sp that parsed it! 00622 typeNs = tnsUri_,elemNs = tnsUri_; 00623 Constraint* c=0; 00624 int type_id = 0, minimum = 1, maximum = 1, attcnt; 00625 Qname refName; 00626 bool qualified = false,nill = false; 00627 XSDType *elemType; 00628 fwdRef=false; 00629 attcnt = xParser_->getAttributeCount(); 00630 for (int i = 0; i < attcnt; i++) 00631 { 00632 std::string attName = xParser_->getAttributeName(i); 00633 if ("name" == attName) 00634 name = xParser_->getAttributeValue(i); 00635 00636 else if ("type" == attName) 00637 { 00638 Qname typeName(xParser_->getAttributeValue(i)); 00639 if (type_id > 0) 00640 error 00641 ("<element> : type and ref are mutually exclusive in element decl"); 00642 typeName.setNamespace(typeNs=xParser_->getNamespace(typeName.getPrefix())); 00643 type_id = getTypeId(typeName, true); 00644 if (type_id == 0) 00645 error("<element>:Could not resolve type " + 00646 typeName.getNamespace() + ":" + 00647 typeName.getLocalName(),0); 00648 } 00649 00650 else if ("form" == attName) 00651 { 00652 if ("qualified" == xParser_->getAttributeValue(i)) 00653 qualified = true; 00654 00655 else if ("unqualified" == xParser_->getAttributeValue(i)) 00656 qualified = false; 00657 else 00658 error("<element>:Invalid value for form in element " + 00659 name,1); 00660 } 00661 00662 else if ("ref" == attName) 00663 { 00664 if (!name.empty()) 00665 error 00666 ("<element>:name and ref are mutually exclusive in element decl"); 00667 if (type_id > 0) 00668 error 00669 ("<element>:type and ref are mutually exclusive in element decl"); 00670 refName = xParser_->getAttributeValue(i); 00671 refName.setNamespace(xParser_->getNamespace(refName.getPrefix())); 00672 Element *e=0; 00673 elemNs = refName.getNamespace(); 00674 00675 if(refName.getNamespace()==tnsUri_){ 00676 00677 e = const_cast<Element*>(getElement(refName)); 00678 if (e) 00679 type_id = e->getType(); 00680 } 00681 else{ 00682 //The referenced element may be in an imported schemaparser 00683 int i=checkImport(refName.getNamespace()); 00684 if(i>=0 && importedSchemas_[i].sParser) { 00685 00686 e=const_cast<Element*>(importedSchemas_[i].sParser->getElement(refName)); 00687 if (e){ 00688 //if the type is in an imported schema then we must add a local reference to 00689 // its type,because the type id as got by e->getType() 00690 // is not valid in the current schema context 00691 const XSDType* pType = importedSchemas_[i].sParser->getType(e->getType()); 00692 type_id= typesTable_.addExternalTypeId(e->getName()+"_"+e->getTypeNamespace(), 00693 pType); 00694 } 00695 } 00696 } 00697 00698 if (e == 0){ 00699 00700 fwdRef=true; 00701 name=refName.getLocalName(); 00702 lForwardElemRefs_.push_back(refName); 00703 //this will be resolved later 00704 } 00705 else{ 00706 name = e->getName(); 00707 qualified = e->isQualified(); 00708 defaultVal = e->defaultVal(); 00709 fixedVal = e->fixedVal(); 00710 typeNs = e->getTypeNamespace(); 00711 elemNs = e->getNamespace(); 00712 } 00713 00714 #ifdef LOGGING 00715 logFile_<<elemNs<<":"<<name<<" -> element reference("<<type_id<<")"<<std::endl; 00716 #endif 00717 00718 } 00719 else if ("minOccurs" == attName){ 00720 minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10); 00721 } 00722 else if ("maxOccurs" == attName){ 00723 if ("unbounded" == xParser_->getAttributeValue(i)) 00724 maximum = UNBOUNDED; 00725 else 00726 maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10); 00727 if (maximum == -1){ //invalid value for maxOccurs 00728 error("<element>:Invalid value for maxOccurs",1); 00729 maximum=1; 00730 } 00731 } 00732 else if ("default" == attName){ 00733 if (fixedVal.empty()) 00734 defaultVal = xParser_->getAttributeValue(i); 00735 00736 else 00737 error("<element>:fixed and default cannot occur together"); 00738 } 00739 else if ("fixed" == attName){ 00740 if (defaultVal.empty()) 00741 fixedVal = xParser_->getAttributeValue(i); 00742 00743 else 00744 error("<element>:fixed and default cannot occur together"); 00745 } 00746 00747 else if ("substitutionGroup" == attName) { 00748 00749 //do nothing 00750 } 00751 else if ("nillable" == attName) { 00752 00753 //a nillable element need not have a type ,so set it to anyType id if nop type was given 00754 nill = true; 00755 minimum = 0; 00756 } 00757 else 00758 error("<element>:Unsupported Attribute "+attName ,2) ; 00759 } 00760 00761 do 00762 { 00763 xParser_->nextTag(); 00764 std::string elemName=xParser_->getName(); 00765 if (xParser_->getEventType() == xParser_->END_TAG) { 00766 if (elemName == "element") 00767 break; 00768 00769 //if an end tag is seen proceed till next start tag 00770 while (xParser_->getEventType() != xParser_->START_TAG) 00771 xParser_->nextTag(); 00772 } 00773 00774 if (elemName == "complexType"){ 00775 elemType = parseComplexType(); 00776 type_id = typesTable_.addType(elemType); 00777 typeNs = elemType->getNamespace(); 00778 } 00779 else if (elemName == "simpleType"){ 00780 elemType = parseSimpleType(); 00781 type_id = typesTable_.addType(elemType); 00782 typeNs = elemType->getNamespace(); 00783 } 00784 else if (elemName == "annotation"){ 00785 parseAnnotation(); 00786 } 00787 else if( elemName=="key") { 00788 if (c) 00789 delete c; 00790 c=parseConstraint(Schema::Key); 00791 } 00792 else if( elemName=="keyref") { 00793 if (c) 00794 delete c; 00795 c=parseConstraint(Schema::Keyref); 00796 } 00797 else if( elemName=="unique") { 00798 if (c) 00799 delete c; 00800 c=parseConstraint(Schema::Unique); 00801 } 00802 else{ 00803 error("<element> : syntax error or unkown tag :"+elemName); 00804 } 00805 } 00806 while (true); 00807 00808 if (nill && type_id == 0) { 00809 type_id = Schema::XSD_ANYTYPE; 00810 } 00811 00812 constraints_.push_back(c); 00813 Element e(name, 00814 elemNs, 00815 typeNs, 00816 type_id, 00817 minimum, 00818 maximum, 00819 qualified, 00820 defaultVal, 00821 fixedVal); 00822 e.addConstraint(c); 00823 return e; 00824 } 00825 00826 Constraint* 00827 SchemaParser::parseConstraint(Schema::ConstraintType cstr) 00828 { 00829 Constraint * c= new Constraint(cstr); 00830 c->setName(xParser_->getAttributeValue("","name")); 00831 00832 do 00833 { 00834 xParser_->nextTag(); 00835 std::string elemName=xParser_->getName(); 00836 if (xParser_->getEventType() == xParser_->END_TAG) { 00837 if (cstr==Schema::Key && elemName == "key" || 00838 cstr==Schema::Keyref && elemName == "keyref" || 00839 cstr==Schema::Unique && elemName == "unique" ) 00840 break; 00841 00842 //if an end tag is seen proceed till next start tag 00843 while (xParser_->getEventType() != xParser_->START_TAG) 00844 xParser_->nextTag(); 00845 } 00846 if(elemName=="selector"){ 00847 c->setSelector(xParser_->getAttributeValue("", "xpath")); 00848 xParser_->nextTag(); 00849 } 00850 else if(elemName=="field"){ 00851 c->addField(xParser_->getAttributeValue("", "xpath")); 00852 xParser_->nextTag(); 00853 } 00854 }while (true); 00855 return c; 00856 } 00857 00858 00859 Element 00860 SchemaParser::addAny(ContentModel* cm) 00861 { 00862 std::string ns; 00863 00864 int type_id = Schema::XSD_ANY, minimum = 1, maximum = 1, attcnt; 00865 //note processContents=lax . 00866 attcnt = xParser_->getAttributeCount(); 00867 for (int i = 0; i < attcnt; i++) 00868 { 00869 std::string attr = xParser_->getAttributeName(i); 00870 if ("namespace" == attr) 00871 ns = xParser_->getAttributeValue(i); 00872 00873 else if ("minOccurs" == attr) 00874 minimum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10); 00875 00876 else if ("maxOccurs" == attr) 00877 { 00878 if ("unbounded" == xParser_->getAttributeValue(i)) 00879 maximum = UNBOUNDED; 00880 else 00881 maximum = XmlUtils::parseInt(xParser_->getAttributeValue(i), 10); 00882 if (maximum == -1){ //invalid value for maxOccurs 00883 error("<element>:Invalid value for maxOccurs",1); 00884 maximum=1; 00885 } 00886 } 00887 00888 else if ("processContents" == attr || "id" == attr) { 00889 00890 //do nothing 00891 } 00892 else 00893 error("<any>:Unsupported Attribute "+attr,2); 00894 } 00895 00896 xParser_->nextTag(); 00897 do 00898 { 00899 if (xParser_->getEventType() == xParser_->END_TAG) 00900 { 00901 if (xParser_->getName() == "any") 00902 break; 00903 00904 } 00905 xParser_->nextToken(); 00906 }while (true); 00907 00908 00909 Element e(ns, 00910 ns, 00911 ns, 00912 type_id, 00913 minimum, 00914 maximum); 00915 00916 cm->addElement(e); 00917 return e; 00918 } 00919 00920 00921 Attribute 00922 SchemaParser::addAnyAttribute(ComplexType * cType) 00923 { 00924 std::string ns; 00925 int type_id = Schema::XSD_ANY,attcnt; 00926 bool qualified = true; 00927 00928 //note processContents=lax . 00929 attcnt = xParser_->getAttributeCount(); 00930 for (int i = 0; i < attcnt; i++) 00931 { 00932 std::string attr = xParser_->getAttributeName(i); 00933 if ("namespace" == attr) 00934 ns = xParser_->getAttributeValue(i); 00935 00936 else if ("processContents" == attr || "id" == attr) 00937 { 00938 00939 //do nothing 00940 } 00941 else 00942 error("<anyAttribute>:Unsupported Attribute "+attr,1); 00943 } 00944 00945 Attribute a(ns, 00946 type_id, 00947 qualified); 00948 if(cType) 00949 cType->addAttribute(a); 00950 xParser_->nextTag(); 00951 while (xParser_->getName() == "annotation") 00952 { 00953 parseAnnotation(); 00954 xParser_->nextTag(); 00955 } 00956 return a; 00957 00958 } 00959 00960 00961 //This function parses and attribute 00962 Attribute 00963 SchemaParser::parseAttribute(bool & fwdRef) 00964 { 00965 std::string name, fixedVal, defaultVal; 00966 int type_id = 0, attcnt; 00967 bool qualified = false, use = false; 00968 fwdRef=false; 00969 00970 Qname refAttribute; 00971 attcnt = xParser_->getAttributeCount(); 00972 for (int i = 0; i < attcnt; i++) { 00973 std::string attName = xParser_->getAttributeName(i); 00974 std::string attNs=xParser_->getAttributeNamespace(i); 00975 std::string attVal=xParser_->getAttributeValue(i); 00976 00977 00978 if ("name" == attName) 00979 name = attVal; 00980 else if ("type" == attName) { 00981 if (type_id > 0) 00982 error("<attribute>:type and ref are mutually exclusive in element decl"); 00983 Qname typeName(attVal); 00984 typeName.setNamespace(xParser_-> 00985 getNamespace(typeName.getPrefix())); 00986 type_id = getTypeId(typeName, true); 00987 if (type_id == 0) 00988 error("<attribute>:Could not resolve type " + 00989 typeName.getNamespace() + 00990 ":" +typeName.getLocalName(),1); 00991 } 00992 else if ("form" == attName) { 00993 if ("qualified" == attVal) 00994 qualified = true; 00995 else 00996 qualified = false; 00997 } 00998 else if ("ref" == attName) { 00999 if (!name.empty()) 01000 error("<attribute>:name and ref are mutually exclusive in element decl"); 01001 if (type_id > 0) 01002 error("<attribute>:type and ref are mutually exclusive in element decl"); 01003 refAttribute = attVal; 01004 refAttribute.setNamespace(xParser_->getNamespace(refAttribute.getPrefix())); 01005 Attribute *a =0; 01006 if(refAttribute.getNamespace()==tnsUri_){ 01007 a=getAttribute(refAttribute); 01008 }else{ 01009 int i=checkImport(refAttribute.getNamespace()); 01010 if(i >=0 && importedSchemas_[i].sParser){ 01011 a=importedSchemas_[i].sParser->getAttribute(refAttribute); 01012 } 01013 else 01014 a=0; 01015 } 01016 01017 if (a == 0){ 01018 fwdRef = true; 01019 name=refAttribute.getLocalName(); 01020 lForwardAttributeRefs_.push_back(refAttribute); 01021 } 01022 else{ 01023 name = a->getName(); 01024 type_id = a->getType(); 01025 qualified = a->isQualified(); 01026 if (defaultVal.empty()) 01027 defaultVal = a->defaultVal(); 01028 if (fixedVal.empty()) 01029 fixedVal = a->fixedVal(); 01030 } 01031 } 01032 else if ("default" == attName) { 01033 if (fixedVal.empty()) 01034 defaultVal = attVal; 01035 else 01036 error 01037 ("<attribute>:fixed and default cannot occur together"); 01038 } 01039 else if ("fixed" == attName) { 01040 if (defaultVal.empty()) 01041 fixedVal = attVal; 01042 else 01043 error("<attribute>:fixed and default cannot occur together"); 01044 } 01045 else if ("use" == attName) { 01046 if (attVal == "required") 01047 use = true; 01048 else 01049 use = false; 01050 } 01051 else { 01052 int n=-1; 01053 if(!attNs.empty() && ((n=checkImport(attNs))!=-1)){ 01054 fixedVal=attNs;//hack for non schema attributes 01055 defaultVal=attVal;//store non schema attributes.esp for soapenc:arrayType 01056 }else{ 01057 error("<attribute>:Unsupported attribute {"+ attNs+ "}:"+attName,2); 01058 } 01059 } 01060 } 01061 //Now parse the children of the attribute tag viz simpleType 01062 do 01063 { 01064 xParser_->nextTag(); 01065 if (xParser_->getEventType() == xParser_->END_TAG) 01066 { 01067 if (xParser_->getName() == "attribute") 01068 break; 01069 01070 //if an end tag is seen proceed till next start tag 01071 while (xParser_->getEventType() != xParser_->START_TAG) 01072 xParser_->nextTag(); 01073 } 01074 01075 else if (xParser_->getName() == "simpleType") 01076 { 01077 XSDType *elemType = parseSimpleType(); 01078 01079 //create an anonymous type 01080 type_id = typesTable_.addType(elemType); 01081 } 01082 01083 else if (xParser_->getName() == "annotation") 01084 parseAnnotation(); 01085 else 01086 error("<attribute>:Syntax error or unkown tag "+xParser_->getName()); 01087 } 01088 while (true); 01089 01090 Attribute a(name, 01091 type_id, 01092 qualified, 01093 defaultVal, 01094 fixedVal, 01095 use); 01096 return a; 01097 01098 } 01099 01100 SimpleType * 01101 SchemaParser::parseSimpleType() 01102 { 01103 SimpleType *st = new SimpleType(tnsUri_); 01104 int basetype_id = 0; 01105 int attcnt; 01106 attcnt = xParser_->getAttributeCount(); 01107 for (int i = 0; i < attcnt; i++) 01108 { 01109 if ("name" == xParser_->getAttributeName(i)) 01110 st->setName(xParser_->getAttributeValue(i)); 01111 01112 else 01113 error("<simpleType> :" + xParser_->getAttributeName(i) + 01114 ":Unknown/Unsupported attribute ",2); 01115 } 01116 01117 do 01118 { 01119 xParser_->nextTag(); 01120 if (xParser_->getEventType() == xParser_->END_TAG) 01121 { 01122 if (xParser_->getName() == "simpleType") 01123 break; 01124 01125 //if an end tag is seen proceed till next start tag 01126 while (xParser_->getEventType() != xParser_->START_TAG) 01127 xParser_->nextTag(); 01128 } 01129 if (xParser_->getName() == "restriction") 01130 { 01131 attcnt = xParser_->getAttributeCount(); 01132 for (int i = 0; i < attcnt; i++) 01133 { 01134 if ("base" == xParser_->getAttributeName(i)) 01135 { 01136 Qname typeName(xParser_->getAttributeValue(i)); 01137 typeName.setNamespace(xParser_-> 01138 getNamespace(typeName. 01139 getPrefix())); 01140 st->setBaseType(basetype_id = 01141 getTypeId(typeName, true)); 01142 if (basetype_id == 0) 01143 error("<simpleType>:" + 01144 xParser_->getAttributeValue(i) + 01145 ":Unknown base type ",1); 01146 } 01147 else 01148 error("<simpleType>:" + xParser_->getAttributeName(i) + 01149 ":Unknown/Unsupported attribute for <restriction>",2); 01150 } 01151 parseRestriction(st); 01152 } 01153 else if (xParser_->getName() == "union"){ 01154 01155 std::string members = xParser_->getAttributeValue("", "memberTypes"); 01156 size_t s = 0; 01157 while(s < members.length()){ 01158 while(members[s]==' ')s++; 01159 std::string type = members.substr(s,members.find(' ',s)-s); 01160 Qname typeName(type); 01161 typeName.setNamespace(xParser_->getNamespace(typeName.getPrefix())); 01162 basetype_id = getTypeId(typeName,true); 01163 st->setUnionType(basetype_id); 01164 s+=type.length()+1; 01165 } 01166 01167 xParser_->nextTag(); 01168 while(xParser_->getName() == "simpleType"){ 01169 XSDType * t = parseSimpleType(); 01170 Schema::Type i = (Schema::Type)typesTable_.addType(t); 01171 01172 st->setUnionType(i); 01173 xParser_->nextTag(); 01174 } 01175 } 01176 else if(xParser_->getName() == "list"){ 01177 01178 basetype_id = getTypeId(xParser_->getAttributeValue("", "itemType")); 01179 st->setListType(basetype_id); 01180 xParser_->nextTag(); 01181 } 01182 else if (xParser_->getName() == "annotation") 01183 parseAnnotation(); 01184 else 01185 error("<simpleType>:Syntax error"); 01186 } 01187 while (true); 01188 return st; 01189 } 01190 01191 void 01192 SchemaParser::parseRestriction(SimpleType * st, 01193 ComplexType * ct) 01194 { 01195 if (st->getBaseTypeId() == 0) 01196 error("<restriction>:unkown BaseType",1); 01197 01198 do { 01199 xParser_->nextTag(); 01200 if (xParser_->getEventType() == xParser_->END_TAG) 01201 { 01202 if (xParser_->getName() == "restriction") 01203 break; 01204 else 01205 xParser_->nextTag(); 01206 if (xParser_->getName() == "restriction" 01207 && xParser_->getEventType() == xParser_->END_TAG) 01208 break; 01209 } 01210 while (xParser_->getName() == "annotation") { 01211 parseAnnotation(); 01212 xParser_->nextTag(); 01213 } 01214 if(xParser_->getName()=="attribute" && ct!=0){ 01215 bool f=false; 01216 Attribute a=parseAttribute(f); 01217 ct->addAttribute(a,f); 01218 } 01219 else if (st->isvalidFacet(xParser_->getName())){ 01220 //This function also sets the facet if valid 01221 01222 st->setFacetValue(xParser_->getName(), 01223 xParser_->getAttributeValue("", "value")); 01224 }else{ 01225 error("<restriction>:" + xParser_->getName() + 01226 " is not a valid facet /attribute for the type",1); 01227 } 01228 } while (true); 01229 } 01230 01231 void 01232 SchemaParser::parseComplexContent(ComplexType * ct) 01233 { 01234 int attcnt = xParser_->getAttributeCount(); 01235 int i = 0; 01236 Qname typeName; 01237 01238 ct->setContentModel(Schema::Complex); 01239 xParser_->nextTag(); 01240 01241 while (xParser_->getName() == "annotation") { 01242 parseAnnotation(); 01243 xParser_->nextTag(); 01244 } 01245 01246 if (xParser_->getName() == "restriction") { 01247 attcnt = xParser_->getAttributeCount(); 01248 for (i = 0; i < attcnt; i++) { 01249 if ("base" == xParser_->getAttributeName(i)) 01250 { 01251 typeName = xParser_->getAttributeValue(i); 01252 typeName.setNamespace(xParser_-> 01253 getNamespace(typeName.getPrefix())); 01254 } 01255 } 01256 ct->setBaseType(getTypeId(typeName, true), 01257 Schema::Restriction); 01258 } 01259 else if (xParser_->getName() == "extension") { 01260 attcnt = xParser_->getAttributeCount(); 01261 for (i = 0; i < attcnt; i++) { 01262 if ("base" == xParser_->getAttributeName(i)) { 01263 typeName = xParser_->getAttributeValue(i); 01264 typeName.setNamespace(xParser_-> 01265 getNamespace(typeName.getPrefix())); 01266 } 01267 } 01268 ct->setBaseType(getTypeId(typeName, true), 01269 Schema::Extension); 01270 } 01271 01272 xParser_->nextTag(); 01273 while (xParser_->getName() == "annotation") { 01274 parseAnnotation(); 01275 xParser_->nextTag(); 01276 } 01277 01278 { 01279 std::string elemName=xParser_->getName(); 01280 ContentModel * cm=0; 01281 if (elemName == "all"){ 01282 cm= new ContentModel(Schema::All); 01283 } 01284 else if (elemName == "sequence"){ 01285 cm= new ContentModel(Schema::Sequence); 01286 } 01287 else if (elemName == "choice"){ 01288 cm= new ContentModel(Schema::Choice); 01289 } 01290 01291 if(cm){ 01292 parseContent(cm); 01293 ct->setContents(cm); 01294 xParser_->nextTag(); 01295 } 01296 01297 //parse any attributes 01298 while (xParser_->getEventType() != xParser_->END_TAG){ 01299 01300 if (xParser_->getName() == "attribute") { 01301 bool f=false; 01302 Attribute a=parseAttribute(f); 01303 ct->addAttribute(a,f); 01304 } 01305 else if(xParser_->getName() == "attributeGroup") 01306 { 01307 parseAttributeGroup(ct); 01308 01309 } 01310 else if (xParser_->getName() == "anyAttribute") 01311 addAnyAttribute(ct); 01312 01313 xParser_->nextTag(); 01314 } 01315 } 01316 01317 do { 01318 if (xParser_->getEventType() == xParser_->END_TAG) 01319 if ((xParser_->getName() == "restriction" || 01320 xParser_->getName() == "extension") ) 01321 break; 01322 xParser_->nextTag(); 01323 } 01324 while (true); 01325 01326 xParser_->nextTag(); 01327 } 01328 01329 01330 void 01331 SchemaParser::parseSimpleContent(ComplexType * ct) 01332 { 01333 ct->setContentModel(Schema::Simple); 01334 xParser_->nextTag(); 01335 if (xParser_->getName() == "restriction") 01336 { 01337 SimpleType *st = new SimpleType(tnsUri_); 01338 int attcnt = xParser_->getAttributeCount(); 01339 int basetype_id = 0; 01340 for (int i = 0; i < attcnt; i++) 01341 { 01342 if ("base" == xParser_->getAttributeName(i)) 01343 { 01344 Qname typeName(xParser_->getAttributeValue(i)); 01345 typeName.setNamespace(xParser_-> 01346 getNamespace(typeName.getPrefix())); 01347 st->setBaseType(basetype_id = getTypeId(typeName, true)); 01348 if (basetype_id == 0) 01349 error("<simpleContent> :" + 01350 xParser_->getAttributeValue(i) + 01351 ":Unknown base type ",1); 01352 } 01353 01354 else 01355 error("<simpleContent> :" + xParser_->getAttributeName(i) + 01356 ":Unknown/Unsupported attribute ",2); 01357 } 01358 parseRestriction(st,ct); 01359 int typeId = typesTable_.addType(st); 01360 ct->setSimpleContentType(typeId); 01361 } 01362 01363 else if (xParser_->getName() == "extension") 01364 { 01365 //This extension does not use the full model that can come in 01366 //ComplexContent .It uses the simple model.no particle allowed ,only attributes 01367 int attcnt = xParser_->getAttributeCount(); 01368 int basetype_id = 0; 01369 for (int i = 0; i < attcnt; i++) 01370 { 01371 if ("base" == xParser_->getAttributeName(i)) 01372 { 01373 Qname typeName(xParser_->getAttributeValue(i)); 01374 typeName.setNamespace(xParser_-> 01375 getNamespace(typeName.getPrefix())); 01376 ct->setSimpleContentType(basetype_id = 01377 getTypeId(typeName, true)); 01378 if (basetype_id == 0) 01379 error("<simpleContent> :" + 01380 xParser_->getAttributeValue(i) + 01381 ":Unknown base type ",1); 01382 } 01383 01384 else 01385 error("<simpleContent> :" + xParser_->getAttributeName(i) + 01386 ":Unknown/Unsupported attribute "); 01387 } 01388 xParser_->nextTag(); 01389 do 01390 { 01391 01392 if (xParser_->getName() == "attribute") 01393 { 01394 bool f=false; 01395 Attribute a=parseAttribute(f); 01396 ct->addAttribute(a,f); 01397 01398 01399 } 01400 else if(xParser_->getName() == "attributeGroup") 01401 { 01402 parseAttributeGroup(ct); 01403 01404 } 01405 01406 else if (xParser_->getName() == "anyAttribute") 01407 addAnyAttribute(ct); 01408 else 01409 break; 01410 xParser_->nextTag(); 01411 }while(true); 01412 01413 if (! 01414 (xParser_->getName() == "extension" 01415 && xParser_->getEventType() == xParser_->END_TAG)) 01416 error("<simpleContent> :Syntax error :extension"); 01417 } 01418 xParser_->nextTag(); 01419 if (! 01420 (xParser_->getName() == "simpleContent" 01421 && xParser_->getEventType() == xParser_->END_TAG)) 01422 error("<simpleContent> :Syntax error "); 01423 } 01424 01425 01426 bool 01427 SchemaParser::parseRedefine() 01428 { 01429 parseInclude(); 01430 resolveFwdRefs_=false; 01431 parseSchema("redefine"); 01432 resolveFwdRefs_=true; 01433 return true; 01434 } 01435 01436 bool 01437 SchemaParser::parseInclude() 01438 { 01439 ifstream xsdStream; 01440 std::string loc = xParser_->getAttributeValue("", "schemaLocation"); 01441 01442 01443 // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases 01444 //in the the test. Will not work for paths like "C:\temp\schema.xsd" .Use the file:/ protocol 01445 01446 01447 if ( loc.find("/",0) != 0 && // not an asolute path 01448 loc.find("file:/",0) == std::string::npos && 01449 loc.find("http://") == std::string::npos) 01450 loc = uri_ + loc; 01451 01452 01453 #ifndef _WIN32 01454 01455 if (!loc.empty()) { 01456 01457 std::string schemaconf= confPath_ + "schema.conf"; 01458 try { 01459 ConfigFile cf(schemaconf); 01460 cf.readInto<std::string>(loc,loc); 01461 }catch (const ConfigFile::file_not_found & e) {} 01462 } 01463 #endif 01464 01465 01466 if(!loc.empty()) 01467 { 01468 if(XmlUtils::fetchUri(loc,fname_)) 01469 { 01470 /* 01471 * If the schema definition was retrieved successfully 01472 * process it and add all type definitions and 01473 * declaration to the current namespace 01474 */ 01475 xsdStream.open(fname_.c_str()); 01476 01477 XmlPullParser * xpp = new XmlPullParser(xsdStream); 01478 XmlPullParser * tmpXparser=xParser_; 01479 xParser_=xpp; 01480 01481 xParser_->setFeature(FEATURE_PROCESS_NAMESPACES, true); 01482 xParser_->require(XmlPullParser::START_DOCUMENT, "", ""); 01483 while (xParser_->getEventType() != xParser_->END_DOCUMENT){ 01484 xParser_->nextTag(); 01485 if (xParser_->getEventType() == xParser_->START_TAG && 01486 xParser_->getName() == "schema"){ 01487 resolveFwdRefs_=false; 01488 01489 if(!parseSchemaTag()) 01490 error("Error while parsing the included schema " + loc); 01491 else{ 01492 01493 resolveFwdRefs_=true; 01494 break; 01495 } 01496 } 01497 } 01498 xParser_=tmpXparser; 01499 delete xpp; 01500 } 01501 else{ 01502 01503 error("Error while opening the included schema " + loc); 01504 } 01505 } 01506 else{ 01507 01508 error("schemaLocation is a required attribute for <include>"); 01509 } 01510 01511 xParser_->nextTag(); 01512 return true; 01513 } 01514 01515 bool 01516 SchemaParser::parseImport() 01517 { 01518 Qname typeName; 01519 std::string xsdFile; 01520 std::string ns = xParser_->getAttributeValue("", "namespace"); 01521 std::string loc=xParser_->getAttributeValue("", "schemaLocation"); 01522 01523 if(ns == tnsUri_) 01524 return parseInclude();//sometimes import is used to import schemas in same ns. 01525 //treat it internally like include 01526 01527 // if (loc.empty()) 01528 // loc = ns; //try using the namespace as schemalocation 01529 01530 // FV Sat Dec 22 15:33:09 CET 2007 I added the absolute path and the file:/ use-cases in the the test 01531 // if ( !loc.empty() && loc.find("http://") == std::string::npos) 01532 // loc = uri_ + loc; 01533 01534 if ( !loc.empty() && 01535 loc.find("/",0) != 0 && // no an asolute path 01536 loc.find("file:/",0) == std::string::npos && 01537 loc.find("http://") == std::string::npos) 01538 loc = uri_ + loc; 01539 01540 #ifndef _WIN32 01541 if (!loc.empty()) { 01542 01543 std::string schemaconf= confPath_ + "schema.conf"; 01544 try { 01545 ConfigFile cf(schemaconf); 01546 cf.readInto<std::string>(loc,loc); 01547 }catch (const ConfigFile::file_not_found &e) {} 01548 } 01549 #endif 01550 01551 if(!loc.empty()) 01552 { 01553 if(XmlUtils::fetchUri(loc,xsdFile)) 01554 { 01555 /* 01556 * If the schema definition was retrieved successfully 01557 * process it and add it to list of imported schemas 01558 */ 01559 SchemaParser *sp = new SchemaParser(xsdFile,ns); 01560 sp->setUri(uri_); 01561 //pass the imports to the new schema parser 01562 for (size_t i = 0; i < importedSchemas_.size(); i++) { 01563 01564 if(importedSchemas_[i].sParser ) { 01565 sp->addImport(importedSchemas_[i].sParser); 01566 } 01567 } 01568 01569 if(sp->parseSchemaTag()) 01570 addImport(sp); 01571 else 01572 error("Error while parsing imported namespace "+ns,0); 01573 01574 } 01575 else{ 01576 01577 error("could not import namespace from location "+loc); 01578 } 01579 } 01580 else{ 01581 // if no location is mentioned ,just add the namespace,types will be resolved later 01582 01583 addImport(ns); 01584 } 01585 01586 error("Imported namespace "+ns+" from " + loc,2); 01587 01588 if (loc.empty()) 01589 error("No location supplied for the import"+ns,2); 01590 01591 xParser_->nextTag(); 01592 return true; 01593 } 01594 01595 bool SchemaParser::isBasicType(int sType) const 01596 { 01597 if (sType > Schema::XSD_ANYURI || sType <= Schema::XSD_INVALID) 01598 return false; 01599 01600 else 01601 return true; 01602 } 01603 01604 01605 //This function gets the id of a type whose Qname is passed. 01606 //The Qname struct if it has a prefix must either be a valid namespace 01607 //default is http://www.w3.org/2001/XMLSchema 01608 //This function has two modes 01609 //if 'create' is true a new type is created (for fwd references) 01610 //otherwise the existing list of parsed types is used for resolution 01611 01612 int 01613 SchemaParser::getTypeId( const Qname & type, bool create) 01614 { 01615 std::string typens = type.getNamespace(); 01616 if (typens.empty()|| 01617 typens == tnsUri_ || 01618 typens == Schema::SchemaUri){ 01619 01620 return typesTable_.getTypeId(type, create); 01621 } 01622 else { 01623 //postpone resolution till matchExtRefs is called 01624 if (importedSchemas_.size() == 0 && create) { 01625 01626 return typesTable_.addExternalTypeId(type, 0); 01627 } 01628 01629 //search in the array of imported schemas 01630 int typeId = 0; 01631 for (size_t i = 0; i < importedSchemas_.size(); i++) { 01632 01633 if ( importedSchemas_[i].ns == type.getNamespace()) { 01634 01635 if(importedSchemas_[i].sParser ) { 01636 01637 typeId = importedSchemas_[i].sParser->getTypeId(type, false); 01638 //get the type definition from the imported namespace schema parser and 01639 // add a reference to the current schema parser 01640 if (typeId) { 01641 return typesTable_.addExternalTypeId(type, 01642 (XSDType *) importedSchemas_[i].sParser->getType(typeId)); 01643 } 01644 else 01645 return 0; 01646 } 01647 } 01648 } 01649 if (create){ 01650 //automatically add an unreferenced namespace as an import 01651 addImport(type.getNamespace()); 01652 return typesTable_.addExternalTypeId(type, 0); 01653 } 01654 } 01655 return XSD_INVALID; 01656 } 01657 01658 01659 //resolves any external references with the imported schemas 01660 //This method must be called to ensure resolution of all types 01661 bool SchemaParser::finalize(void) 01662 { 01663 int unresolved=typesTable_.getNumExtRefs(); 01664 if(unresolved > 0) { 01665 for (int i = 0; i < unresolved; i++){ 01666 01667 Qname & type = typesTable_.getExtRefName(i); 01668 int localId = typesTable_.getExtRefType(i); 01669 01670 //search in the array of imported schemas 01671 int typeId = 0; 01672 for (size_t n = 0; n < importedSchemas_.size(); n++) 01673 { 01674 if (importedSchemas_[n].ns == type.getNamespace()) 01675 { 01676 if(importedSchemas_[n].sParser){ 01677 typeId = importedSchemas_[n].sParser->getTypeId(type); 01678 if (typeId != 0) 01679 typesTable_.addExtType((XSDType *) importedSchemas_[n].sParser->getType(typeId), 01680 localId); 01681 } 01682 } 01683 } 01684 01685 if (typeId == 0) { 01686 01687 logFile_<<"Undefined type "<<type<<std::endl; 01688 } 01689 } 01690 } 01691 if (typesTable_.detectUndefinedTypes()) 01692 { 01693 typesTable_.printUndefinedTypes(logFile_);logFile_.flush(); 01694 logFile_<<"Unresolved types in namespace "<<tnsUri_<<std::endl; 01695 return false; 01696 } 01697 01698 else{ 01699 01700 return true; 01701 } 01702 01703 } 01704 01705 01706 //resolves any forward references of the kind<element ref=Qname... > 01707 void 01708 SchemaParser::resolveForwardElementRefs() 01709 { 01710 bool errors=false; 01711 if (lForwardElemRefs_.empty()) 01712 return; 01713 for (list < Qname >::iterator pQnames = lForwardElemRefs_.begin(); 01714 pQnames != lForwardElemRefs_.end(); pQnames++) { 01715 01716 // cout<<*pQnames<<std::endl; 01717 Element *e = const_cast<Element*>(getElement(*pQnames)); 01718 //TODO , in case the forward ref is in an imported schema we cant just copy the type id 01719 //it needs to be changed to make it a valid type id in current schema 01720 if (e) 01721 typesTable_.resolveForwardElementRefs(pQnames->getLocalName(),*e); 01722 else { 01723 error("Could not resolve element reference "+pQnames->getLocalName(),1); 01724 errors=true; 01725 } 01726 } 01727 if(errors) 01728 error("Unresolved element references",1); 01729 } 01730 01731 01732 void 01733 SchemaParser::resolveForwardAttributeRefs() 01734 { 01735 bool errors=false; 01736 if (lForwardAttributeRefs_.empty()) 01737 return; 01738 for (list < Qname >::iterator pQnames = lForwardAttributeRefs_.begin(); 01739 pQnames != lForwardAttributeRefs_.end(); pQnames++) 01740 { 01741 Attribute *a = getAttribute(*pQnames); 01742 if (a) 01743 typesTable_.resolveForwardAttributeRefs(pQnames-> getLocalName(), *a); 01744 else { 01745 error("Could not resolve attribute reference {"+pQnames->getNamespace() 01746 +"}"+pQnames->getLocalName(),1); 01747 errors=true; 01748 } 01749 } 01750 if(errors) 01751 error("Unresolved attributes references"); 01752 } 01753 01754 01755 //get the element id of a globally declared element 01756 const Element* 01757 SchemaParser::getElement(const Qname & element,bool checkImports)const 01758 { 01759 std::string typens = element.getNamespace(); 01760 if (typens.empty()) 01761 typens = tnsUri_; 01762 if (typens== tnsUri_ || typens == Schema::SchemaUri) 01763 { 01764 int i = 0; 01765 //check if it is a global element 01766 for (std::list<Element>::const_iterator eli=lElems_.begin(); 01767 eli!= lElems_.end(); 01768 eli++,i++) 01769 if (eli->getName() == element.getLocalName()) 01770 return &(*eli); 01771 return 0; 01772 } 01773 else if (checkImports) 01774 { //search imported namespaces 01775 for (size_t i = 0; i < importedSchemas_.size(); i++) 01776 { 01777 if ( importedSchemas_[i].ns == typens) 01778 { 01779 if(importedSchemas_[i].sParser ) 01780 { 01781 return importedSchemas_[i].sParser->getElement(element); 01782 } 01783 } 01784 } 01785 } 01786 return 0; 01787 } 01788 01789 //get the attribute id of a globally declared attribute 01790 Attribute* 01791 SchemaParser::getAttribute(const Qname & attribute) 01792 { 01793 std::string typens = attribute.getNamespace(); 01794 if (typens.empty()) 01795 typens = tnsUri_; 01796 01797 if (typens == tnsUri_ || typens == Schema::SchemaUri) { 01798 //check if it is a global attribute 01799 for(std::list<Attribute>::iterator ali=lAttributes_.begin(); 01800 ali!=lAttributes_.end(); 01801 ali++) 01802 if (ali->getName() == attribute.getLocalName()) 01803 return &(*ali); 01804 }else { 01805 //search imported namespaces 01806 for (size_t i = 0; i < importedSchemas_.size(); i++) 01807 { 01808 if ( importedSchemas_[i].ns == typens) 01809 { 01810 if(importedSchemas_[i].sParser ) 01811 { 01812 return importedSchemas_[i].sParser->getAttribute(attribute); 01813 } 01814 } 01815 } 01816 } 01817 return 0; 01818 } 01819 01820 //get the element id of a globally declared element 01821 Group* 01822 SchemaParser::getGroup(const Qname & name) 01823 { 01824 std::string typens = name.getNamespace(); 01825 if (typens.empty()) 01826 typens = tnsUri_; 01827 if (typens== tnsUri_ || typens == Schema::SchemaUri) 01828 { 01829 01830 //check if it is a global group 01831 for (std::list<Group>::iterator gli =lGroups_.begin(); 01832 gli!= lGroups_.end(); 01833 gli++) 01834 if (gli->getName() == name.getLocalName()) 01835 return &(*gli); 01836 return 0; 01837 } 01838 else 01839 { //search imported namespaces 01840 for (size_t i = 0; i < importedSchemas_.size(); i++) 01841 { 01842 if ( importedSchemas_[i].ns == typens) 01843 { 01844 if(importedSchemas_[i].sParser ) 01845 { 01846 return importedSchemas_[i].sParser->getGroup(name); 01847 } 01848 } 01849 } 01850 } 01851 return 0; 01852 } 01853 01854 AttributeGroup* 01855 SchemaParser::getAttributeGroup(const Qname & name) 01856 { 01857 std::string typens = name.getNamespace(); 01858 if (typens.empty()) 01859 typens = tnsUri_; 01860 if (typens== tnsUri_ || typens == Schema::SchemaUri) 01861 { 01862 01863 //check if it is a global group 01864 for (AttributeGroupList::iterator agli = lAttributeGroups_.begin(); 01865 agli!= lAttributeGroups_.end(); 01866 agli++) 01867 if ((*agli)->getName() == name.getLocalName()) 01868 return (*agli); 01869 return 0; 01870 } 01871 else 01872 { //search imported namespaces 01873 for (size_t i = 0; i < importedSchemas_.size(); i++) 01874 { 01875 if ( importedSchemas_[i].ns == typens) 01876 { 01877 if(importedSchemas_[i].sParser ) 01878 { 01879 return importedSchemas_[i].sParser->getAttributeGroup(name); 01880 } 01881 } 01882 } 01883 } 01884 return 0; 01885 } 01886 01887 std::string 01888 SchemaParser::getNamespace(void) const 01889 { 01890 return tnsUri_; 01891 } 01892 01893 01894 const XSDType * 01895 SchemaParser::getType(int id) const 01896 { 01897 return (const XSDType *) typesTable_.getTypePtr(id); 01898 } 01899 01900 01901 const XSDType * 01902 SchemaParser::getType(const Qname & type,bool checkImports ) 01903 { 01904 int id; 01905 Qname t=type; 01906 01907 if((id=getTypeId(t,false))==0) 01908 return 0; 01909 else { 01910 const XSDType* pType = (const XSDType *) typesTable_.getTypePtr(id); 01911 if (!checkImports) { 01912 01913 if(pType->getNamespace() != tnsUri_) 01914 return 0; 01915 01916 } 01917 return pType; 01918 } 01919 } 01920 01921 01922 const XSDType * 01923 SchemaParser::getType(int id, std::string &nameSpace) 01924 { 01925 const SchemaParser *sp = getImportedSchema(nameSpace); 01926 if (sp == NULL) 01927 { 01928 return 0; 01929 } 01930 else 01931 { 01932 return sp->getType(id); 01933 } 01934 } 01935 01936 const SchemaParser * 01937 SchemaParser::getImportedSchema(std::string &nameSpace) 01938 { 01939 if (nameSpace.empty()|| nameSpace == tnsUri_ || nameSpace == Schema::SchemaUri) 01940 { 01941 return this; 01942 } 01943 01944 for (size_t i = 0; i < importedSchemas_.size(); i++) 01945 { 01946 if ( importedSchemas_[i].ns == nameSpace) 01947 { 01948 return importedSchemas_[i].sParser; 01949 } 01950 } 01951 return NULL; 01952 } 01953 01954 list < const XSDType *>* 01955 SchemaParser::getAllTypes() const 01956 { 01957 list < const XSDType *>*pLTypes = new list < const XSDType * >; 01958 for (int i = 0; i < getNumTypes(); i++) 01959 { 01960 const XSDType *pType = getType(i + Schema::XSD_ANYURI + 1); 01961 pLTypes->push_back(pType); 01962 } 01963 return pLTypes; 01964 } 01965 01966 01967 int 01968 SchemaParser::getNumTypes() const 01969 { 01970 return typesTable_.getNumTypes(); 01971 } 01972 01973 01974 int 01975 SchemaParser::getNumElements() const 01976 { 01977 return lElems_.size(); 01978 } 01979 01980 01981 int 01982 SchemaParser::getNumAttributes() const 01983 { 01984 return lAttributes_.size(); 01985 } 01986 01987 //To be deprecated 01988 bool 01989 SchemaParser::addImports(const std::vector<SchemaParser *> & schemaParsers) 01990 { 01991 for (size_t i=0;i<schemaParsers.size() ;i++){ 01992 01993 if(schemaParsers[i]->getNamespace()!=tnsUri_){ 01994 01995 addImport(schemaParsers[i]); 01996 } 01997 } 01998 return true; 01999 } 02000 02001 bool 02002 SchemaParser::addImport(SchemaParser *sp) 02003 { 02004 //check if the namespace is added in the import list 02005 int i= checkImport(sp->getNamespace()); 02006 // std::cout<<"Copying imports to "<<sp->tnsUri_<<std::endl; 02007 // sp->copyImports(this); 02008 if(i>=0) { 02009 importedSchemas_[i].sParser=sp; 02010 importedSchemas_[i].ns=sp->getNamespace(); 02011 } 02012 else { 02013 //if this was a new import increment 02014 ImportedSchema imp; 02015 imp.sParser=sp; 02016 imp.ns=sp->getNamespace(); 02017 importedSchemas_.push_back(imp); 02018 } 02019 return true; 02020 } 02021 02022 void 02023 SchemaParser::copyImports(SchemaParser * sp) 02024 { 02025 for(size_t i=0;i<importedSchemas_.size();i++) { 02026 02027 if (importedSchemas_[i].sParser) 02028 sp->addImport(importedSchemas_[i].sParser); 02029 } 02030 } 02031 02032 int 02033 SchemaParser::checkImport(std::string nsp)const 02034 { 02035 for(size_t i=0;i<importedSchemas_.size();i++) 02036 { 02037 if(importedSchemas_[i].ns==nsp) 02038 return i; 02039 } 02040 return -1; 02041 } 02042 02043 bool 02044 SchemaParser::addImport(std::string ns, 02045 std::string location) 02046 { 02047 02048 int i= checkImport(ns); 02049 if(i==-1) { 02050 ImportedSchema imp; 02051 imp.sParser=0; 02052 imp.ns=ns; 02053 importedSchemas_.push_back(imp); 02054 i =importedSchemas_.size()-1; 02055 }else { 02056 return true; 02057 } 02058 02059 if(location.empty()) 02060 return true; 02061 std::string xsdFile; 02062 if(XmlUtils::fetchUri(location,xsdFile)) 02063 { 02064 /* 02065 * If the schema definition was retrieved successfully 02066 * process it and add it to list of imported schemas 02067 */ 02068 SchemaParser *sp = new SchemaParser(xsdFile,ns); 02069 sp->setUri(uri_); 02070 if(sp->parseSchemaTag()) 02071 { 02072 importedSchemas_[i].sParser=sp; 02073 return true; 02074 } 02075 else return false; 02076 } 02077 else return false; 02078 02079 } 02080 02081 02082 void SchemaParser::error(std::string mesg, int level) 02083 { 02084 02085 if (level == 0) { 02086 02087 SchemaParserException spe(mesg + "\nFatal Error in SchemaParser\n"); 02088 spe.line = xParser_->getLineNumber(); 02089 spe.col = xParser_->getColumnNumber(); 02090 throw spe; 02091 } 02092 02093 else if (level_ >=1 && level == 1){ 02094 02095 logFile_ << "Error @" << xParser_-> 02096 getLineNumber() << ":" << xParser_-> 02097 getColumnNumber() << XmlUtils::dbsp << mesg << endl; 02098 } 02099 else if (level_ >= 2 && level == 2) { 02100 02101 logFile_ << "Alert @" << xParser_-> 02102 getLineNumber() << ":" << xParser_-> 02103 getColumnNumber() << XmlUtils::dbsp << mesg << endl; 02104 02105 } 02106 } 02107 02108 02109 int 02110 SchemaParser::getBasicContentType(int typeId)const 02111 { 02112 const XSDType *pType = getType(typeId); 02113 int id = typeId; 02114 if (pType != 0) { 02115 02116 /* 02117 It could be a complex type with 02118 simple content or a schema defined simpleType 02119 */ 02120 if (pType->isSimple() == false){ 02121 02122 const ComplexType * cType= static_cast<const ComplexType*> (pType); 02123 02124 if(cType->getContentModel()==Schema::Simple){ 02125 02126 id = cType->getContentType(); 02127 } 02128 else { 02129 02130 return Schema::XSD_INVALID; 02131 } 02132 } 02133 else{ 02134 02135 id = (static_cast<const SimpleType *>(pType))->getBaseTypeId(); 02136 } 02137 id = getBasicContentType(id); 02138 } 02139 return id; 02140 } 02141 02142 std::string 02143 SchemaParser::getTypeName(Schema::Type t)const 02144 { 02145 if (isBasicType(t)){ 02146 return typesTable_.getAtomicTypeName(t); 02147 } 02148 else { 02149 const XSDType * pType = (const XSDType *) typesTable_.getTypePtr(t); 02150 if (pType) 02151 return pType->getName(); 02152 } 02153 return ""; 02154 } 02155 02156 02157 //handle soap arrays .this is really a special case.more like a hack 02158 bool 02159 SchemaParser::makeListFromSoapArray (ComplexType * ct) 02160 { 02161 const XSDType * baseType=getType(ct->getBaseTypeId()); 02162 if (baseType) { 02163 if(baseType->getNamespace()== "http://schemas.xmlsoap.org/soap/encoding/" && 02164 baseType->getName()=="Array"){ 02165 02166 const Attribute* a = ct->getAttribute("arrayType"); 02167 if (!a) 02168 return false; 02169 02170 std::string array = a->defaultVal(); 02171 Qname q(array); 02172 array = q.getLocalName(); 02173 while (array[array.length()-1] ==']' && 02174 array[array.length()-2] =='[') 02175 array = array.substr(0,array.length()-2); 02176 02177 std::string arrayNs = xParser_->getNamespace(q.getPrefix()); 02178 q = Qname(array); 02179 q.setNamespace(arrayNs); 02180 Schema::Type t = (Schema::Type)getTypeId(q,true); 02181 Element e("*",tnsUri_,tnsUri_,t,0,UNBOUNDED); 02182 if (ct->getContents() == 0){ 02183 ContentModel * cm = new ContentModel(Schema::Sequence); 02184 ct->setContents(cm); 02185 } 02186 ct->getContents()->addElement(e); 02187 return true; 02188 } 02189 } 02190 return false; 02191 } 02192 }