GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00024 // --------------------------------------------------------------------------- 00025 // Includes 00026 // --------------------------------------------------------------------------- 00027 #include <xercesc/validators/schema/XSDDOMParser.hpp> 00028 #include <xercesc/validators/schema/SchemaSymbols.hpp> 00029 #include <xercesc/internal/XMLScanner.hpp> 00030 #include <xercesc/internal/ElemStack.hpp> 00031 #include <xercesc/dom/DOMDocument.hpp> 00032 #include <xercesc/dom/impl/DOMElementImpl.hpp> 00033 #include <xercesc/dom/impl/DOMAttrImpl.hpp> 00034 #include <xercesc/dom/impl/DOMTextImpl.hpp> 00035 #include <xercesc/framework/XMLValidityCodes.hpp> 00036 00037 XERCES_CPP_NAMESPACE_BEGIN 00038 00039 // --------------------------------------------------------------------------- 00040 // XSDDOMParser: Constructors and Destructor 00041 // --------------------------------------------------------------------------- 00042 XSDDOMParser::XSDDOMParser( XMLValidator* const valToAdopt 00043 , MemoryManager* const manager 00044 , XMLGrammarPool* const gramPool): 00045 XercesDOMParser(valToAdopt, manager, gramPool) 00046 , fSawFatal(false) 00047 , fAnnotationDepth(-1) 00048 , fInnerAnnotationDepth(-1) 00049 , fDepth(-1) 00050 , fUserErrorReporter(0) 00051 , fUserEntityHandler(0) 00052 , fURIs(0) 00053 , fAnnotationBuf(1023, manager) 00054 00055 { 00056 fURIs = new (manager) ValueVectorOf<unsigned int>(16, manager); 00057 fXSDErrorReporter.setErrorReporter(this); 00058 setValidationScheme(XercesDOMParser::Val_Never); 00059 setDoNamespaces(true); 00060 } 00061 00062 00063 XSDDOMParser::~XSDDOMParser() 00064 { 00065 delete fURIs; 00066 } 00067 00068 00069 // --------------------------------------------------------------------------- 00070 // XSDDOMParser: Helper methods 00071 // --------------------------------------------------------------------------- 00072 DOMElement* XSDDOMParser::createElementNSNode(const XMLCh *namespaceURI, 00073 const XMLCh *qualifiedName) 00074 { 00075 ReaderMgr::LastExtEntityInfo lastInfo; 00076 ((ReaderMgr*) fScanner->getLocator())->getLastExtEntityInfo(lastInfo); 00077 00078 return getDocument()->createElementNS(namespaceURI, qualifiedName, 00079 lastInfo.lineNumber, lastInfo.colNumber); 00080 } 00081 00082 00083 void XSDDOMParser::startAnnotation( const XMLElementDecl& elemDecl 00084 , const RefVectorOf<XMLAttr>& attrList 00085 , const XMLSize_t attrCount) 00086 { 00087 fAnnotationBuf.append(chOpenAngle); 00088 fAnnotationBuf.append(elemDecl.getFullName()); 00089 fAnnotationBuf.append(chSpace); 00090 00091 // attributes are a bit of a pain. To get this right, we have to keep track 00092 // of the namespaces we've seen declared, then examine the namespace context 00093 // for other namespaces so that we can also include them. 00094 // optimized for simplicity and the case that not many 00095 // namespaces are declared on this annotation... 00096 fURIs->removeAllElements(); 00097 for (XMLSize_t i=0; i < attrCount; i++) { 00098 00099 const XMLAttr* oneAttrib = attrList.elementAt(i); 00100 const XMLCh* attrValue = oneAttrib->getValue(); 00101 00102 if (XMLString::equals(oneAttrib->getName(), XMLUni::fgXMLNSString)) 00103 fURIs->addElement(fScanner->getPrefixId(XMLUni::fgZeroLenString)); 00104 else if (!XMLString::compareNString(oneAttrib->getQName(), XMLUni::fgXMLNSColonString, 6)) 00105 fURIs->addElement(fScanner->getPrefixId(oneAttrib->getName())); 00106 00107 fAnnotationBuf.append(oneAttrib->getQName()); 00108 fAnnotationBuf.append(chEqual); 00109 fAnnotationBuf.append(chDoubleQuote); 00110 fAnnotationBuf.append(attrValue); 00111 fAnnotationBuf.append(chDoubleQuote); 00112 fAnnotationBuf.append(chSpace); 00113 } 00114 00115 // now we have to look through currently in-scope namespaces to see what 00116 // wasn't declared here 00117 ValueVectorOf<PrefMapElem*>* namespaceContext = fScanner->getNamespaceContext(); 00118 for (XMLSize_t j=0; j < namespaceContext->size(); j++) 00119 { 00120 unsigned int prefId = namespaceContext->elementAt(j)->fPrefId; 00121 00122 if (!fURIs->containsElement(prefId)) { 00123 00124 const XMLCh* prefix = fScanner->getPrefixForId(prefId); 00125 00126 if (XMLString::equals(prefix, XMLUni::fgZeroLenString)) { 00127 fAnnotationBuf.append(XMLUni::fgXMLNSString); 00128 } 00129 else { 00130 fAnnotationBuf.append(XMLUni::fgXMLNSColonString); 00131 fAnnotationBuf.append(prefix); 00132 } 00133 00134 fAnnotationBuf.append(chEqual); 00135 fAnnotationBuf.append(chDoubleQuote); 00136 fAnnotationBuf.append(fScanner->getURIText(namespaceContext->elementAt(j)->fURIId)); 00137 fAnnotationBuf.append(chDoubleQuote); 00138 fAnnotationBuf.append(chSpace); 00139 00140 fURIs->addElement(prefId); 00141 } 00142 } 00143 00144 fAnnotationBuf.append(chCloseAngle); 00145 fAnnotationBuf.append(chLF); 00146 } 00147 00148 void XSDDOMParser::startAnnotationElement( const XMLElementDecl& elemDecl 00149 , const RefVectorOf<XMLAttr>& attrList 00150 , const XMLSize_t attrCount) 00151 { 00152 fAnnotationBuf.append(chOpenAngle); 00153 fAnnotationBuf.append(elemDecl.getFullName()); 00154 //fAnnotationBuf.append(chSpace); 00155 00156 for(XMLSize_t i=0; i < attrCount; i++) { 00157 00158 const XMLAttr* oneAttr = attrList.elementAt(i); 00159 fAnnotationBuf.append(chSpace); 00160 fAnnotationBuf.append(oneAttr ->getQName()); 00161 fAnnotationBuf.append(chEqual); 00162 fAnnotationBuf.append(chDoubleQuote); 00163 fAnnotationBuf.append(oneAttr->getValue()); 00164 fAnnotationBuf.append(chDoubleQuote); 00165 } 00166 00167 fAnnotationBuf.append(chCloseAngle); 00168 } 00169 00170 void XSDDOMParser::endAnnotationElement( const XMLElementDecl& elemDecl 00171 , bool complete) 00172 { 00173 if (complete) 00174 { 00175 fAnnotationBuf.append(chLF); 00176 fAnnotationBuf.append(chOpenAngle); 00177 fAnnotationBuf.append(chForwardSlash); 00178 fAnnotationBuf.append(elemDecl.getFullName()); 00179 fAnnotationBuf.append(chCloseAngle); 00180 00181 // note that this is always called after endElement on <annotation>'s 00182 // child and before endElement on annotation. 00183 // hence, we must make this the child of the current 00184 // parent's only child. 00185 DOMTextImpl *node = (DOMTextImpl *)fDocument->createTextNode(fAnnotationBuf.getRawBuffer()); 00186 fCurrentNode->appendChild(node); 00187 fAnnotationBuf.reset(); 00188 } 00189 else //capturing character calls 00190 { 00191 fAnnotationBuf.append(chOpenAngle); 00192 fAnnotationBuf.append(chForwardSlash); 00193 fAnnotationBuf.append(elemDecl.getFullName()); 00194 fAnnotationBuf.append(chCloseAngle); 00195 } 00196 } 00197 00198 00199 // --------------------------------------------------------------------------- 00200 // XSDDOMParser: Setter methods 00201 // --------------------------------------------------------------------------- 00202 void XSDDOMParser::setUserErrorReporter(XMLErrorReporter* const errorReporter) 00203 { 00204 fUserErrorReporter = errorReporter; 00205 fScanner->setErrorReporter(this); 00206 } 00207 00208 void XSDDOMParser::setUserEntityHandler(XMLEntityHandler* const entityHandler) 00209 { 00210 fUserEntityHandler = entityHandler; 00211 fScanner->setEntityHandler(this); 00212 } 00213 00214 00215 // --------------------------------------------------------------------------- 00216 // XSDDOMParser: Implementation of the XMLDocumentHandler interface 00217 // --------------------------------------------------------------------------- 00218 void XSDDOMParser::startElement( const XMLElementDecl& elemDecl 00219 , const unsigned int urlId 00220 , const XMLCh* const elemPrefix 00221 , const RefVectorOf<XMLAttr>& attrList 00222 , const XMLSize_t attrCount 00223 , const bool isEmpty 00224 , const bool isRoot) 00225 { 00226 fDepth++; 00227 00228 // while it is true that non-whitespace character data 00229 // may only occur in appInfo or documentation 00230 // elements, it's certainly legal for comments and PI's to 00231 // occur as children of annotation; we need 00232 // to account for these here. 00233 if (fAnnotationDepth == -1) 00234 { 00235 if (XMLString::equals(elemDecl.getBaseName(), SchemaSymbols::fgELT_ANNOTATION) && 00236 XMLString::equals(getURIText(urlId), SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) 00237 { 00238 00239 fAnnotationDepth = fDepth; 00240 startAnnotation(elemDecl, attrList, attrCount); 00241 } 00242 } 00243 else if (fDepth == fAnnotationDepth+1) 00244 { 00245 fInnerAnnotationDepth = fDepth; 00246 startAnnotationElement(elemDecl, attrList, attrCount); 00247 } 00248 else 00249 { 00250 startAnnotationElement(elemDecl, attrList, attrCount); 00251 if(isEmpty) 00252 endElement(elemDecl, urlId, isRoot, elemPrefix); 00253 // avoid falling through; don't call startElement in this case 00254 return; 00255 } 00256 00257 DOMElement *elem; 00258 if (urlId != fScanner->getEmptyNamespaceId()) //TagName has a prefix 00259 { 00260 if (elemPrefix && *elemPrefix) 00261 { 00262 XMLBufBid elemQName(&fBufMgr); 00263 elemQName.set(elemPrefix); 00264 elemQName.append(chColon); 00265 elemQName.append(elemDecl.getBaseName()); 00266 elem = createElementNSNode( 00267 fScanner->getURIText(urlId), elemQName.getRawBuffer()); 00268 } 00269 else { 00270 elem = createElementNSNode( 00271 fScanner->getURIText(urlId), elemDecl.getBaseName()); 00272 } 00273 } 00274 else { 00275 elem = createElementNSNode(0, elemDecl.getBaseName()); 00276 } 00277 00278 DOMElementImpl *elemImpl = (DOMElementImpl *) elem; 00279 for (XMLSize_t index = 0; index < attrCount; ++index) 00280 { 00281 const XMLAttr* oneAttrib = attrList.elementAt(index); 00282 unsigned int attrURIId = oneAttrib->getURIId(); 00283 const XMLCh* namespaceURI = 0; 00284 00285 //for xmlns=... 00286 if (XMLString::equals(oneAttrib->getName(), XMLUni::fgXMLNSString)) 00287 attrURIId = fScanner->getXMLNSNamespaceId(); 00288 00289 //TagName has a prefix 00290 if (attrURIId != fScanner->getEmptyNamespaceId()) 00291 namespaceURI = fScanner->getURIText(attrURIId); //get namespaceURI 00292 00293 // revisit. Optimize to init the named node map to the 00294 // right size up front. 00295 DOMAttrImpl *attr = (DOMAttrImpl *) 00296 fDocument->createAttributeNS(namespaceURI, oneAttrib->getQName()); 00297 attr->setValue(oneAttrib -> getValue()); 00298 DOMNode* remAttr = elemImpl->setAttributeNodeNS(attr); 00299 if (remAttr) 00300 remAttr->release(); 00301 00302 // Attributes of type ID. If this is one, add it to the hashtable of IDs 00303 // that is constructed for use by GetElementByID(). 00304 if (oneAttrib->getType()==XMLAttDef::ID) 00305 { 00306 if (fDocument->fNodeIDMap == 0) 00307 fDocument->fNodeIDMap = new (fDocument) DOMNodeIDMap(500, fDocument); 00308 fDocument->fNodeIDMap->add(attr); 00309 attr->fNode.isIdAttr(true); 00310 } 00311 00312 attr->setSpecified(oneAttrib->getSpecified()); 00313 } 00314 00315 // set up the default attributes 00316 if (elemDecl.hasAttDefs()) 00317 { 00318 XMLAttDefList* defAttrs = &elemDecl.getAttDefList(); 00319 XMLAttDef* attr = 0; 00320 DOMAttrImpl * insertAttr = 0; 00321 00322 for (XMLSize_t i=0; i<defAttrs->getAttDefCount(); i++) 00323 { 00324 attr = &defAttrs->getAttDef(i); 00325 00326 const XMLAttDef::DefAttTypes defType = attr->getDefaultType(); 00327 if ((defType == XMLAttDef::Default) 00328 || (defType == XMLAttDef::Fixed)) 00329 { 00330 // DOM Level 2 wants all namespace declaration attributes 00331 // to be bound to "http://www.w3.org/2000/xmlns/" 00332 // So as long as the XML parser doesn't do it, it needs to 00333 // done here. 00334 const XMLCh* qualifiedName = attr->getFullName(); 00335 XMLBufBid bbPrefixQName(&fBufMgr); 00336 XMLBuffer& prefixBuf = bbPrefixQName.getBuffer(); 00337 int colonPos = -1; 00338 unsigned int uriId = fScanner->resolveQName(qualifiedName, prefixBuf, ElemStack::Mode_Attribute, colonPos); 00339 00340 const XMLCh* namespaceURI = 0; 00341 if (XMLString::equals(qualifiedName, XMLUni::fgXMLNSString)) 00342 uriId = fScanner->getXMLNSNamespaceId(); 00343 00344 //TagName has a prefix 00345 if (uriId != fScanner->getEmptyNamespaceId()) 00346 namespaceURI = fScanner->getURIText(uriId); 00347 00348 insertAttr = (DOMAttrImpl *) fDocument->createAttributeNS( 00349 namespaceURI, qualifiedName); 00350 00351 DOMAttr* remAttr = elemImpl->setDefaultAttributeNodeNS(insertAttr); 00352 if (remAttr) 00353 remAttr->release(); 00354 00355 if (attr->getValue() != 0) 00356 { 00357 insertAttr->setValue(attr->getValue()); 00358 insertAttr->setSpecified(false); 00359 } 00360 } 00361 00362 insertAttr = 0; 00363 attr->reset(); 00364 } 00365 } 00366 00367 fCurrentParent->appendChild(elem); 00368 fCurrentParent = elem; 00369 fCurrentNode = elem; 00370 fWithinElement = true; 00371 00372 // If an empty element, do end right now (no endElement() will be called) 00373 if (isEmpty) 00374 endElement(elemDecl, urlId, isRoot, elemPrefix); 00375 } 00376 00377 00378 00379 void XSDDOMParser::endElement( const XMLElementDecl& elemDecl 00380 , const unsigned int 00381 , const bool 00382 , const XMLCh* const) 00383 { 00384 if(fAnnotationDepth > -1) 00385 { 00386 if (fInnerAnnotationDepth == fDepth) 00387 { 00388 fInnerAnnotationDepth = -1; 00389 endAnnotationElement(elemDecl, false); 00390 } 00391 else if (fAnnotationDepth == fDepth) 00392 { 00393 fAnnotationDepth = -1; 00394 endAnnotationElement(elemDecl, true); 00395 } 00396 else 00397 { // inside a child of annotation 00398 endAnnotationElement(elemDecl, false); 00399 fDepth--; 00400 return; 00401 } 00402 } 00403 00404 fDepth--; 00405 fCurrentNode = fCurrentParent; 00406 fCurrentParent = fCurrentNode->getParentNode (); 00407 00408 // If we've hit the end of content, clear the flag. 00409 // 00410 if (fCurrentParent == fDocument) 00411 fWithinElement = false; 00412 } 00413 00414 void XSDDOMParser::docCharacters( const XMLCh* const chars 00415 , const XMLSize_t length 00416 , const bool cdataSection) 00417 { 00418 // Ignore chars outside of content 00419 if (!fWithinElement) 00420 return; 00421 00422 if (fInnerAnnotationDepth == -1) 00423 { 00424 if (!((ReaderMgr*) fScanner->getReaderMgr())->getCurrentReader()->isAllSpaces(chars, length)) 00425 { 00426 ReaderMgr::LastExtEntityInfo lastInfo; 00427 fScanner->getReaderMgr()->getLastExtEntityInfo(lastInfo); 00428 fXSLocator.setValues(lastInfo.systemId, lastInfo.publicId, lastInfo.lineNumber, lastInfo.colNumber); 00429 fXSDErrorReporter.emitError(XMLValid::NonWSContent, XMLUni::fgValidityDomain, &fXSLocator); 00430 } 00431 } 00432 // when it's within either of the 2 annotation subelements, characters are 00433 // allowed and we need to store them. 00434 else if (cdataSection == true) 00435 { 00436 fAnnotationBuf.append(XMLUni::fgCDataStart); 00437 fAnnotationBuf.append(chars, length); 00438 fAnnotationBuf.append(XMLUni::fgCDataEnd); 00439 } 00440 else 00441 { 00442 for(unsigned int i = 0; i < length; i++ ) 00443 { 00444 if(chars[i] == chAmpersand) 00445 { 00446 fAnnotationBuf.append(chAmpersand); 00447 fAnnotationBuf.append(XMLUni::fgAmp); 00448 fAnnotationBuf.append(chSemiColon); 00449 } 00450 else if (chars[i] == chOpenAngle) 00451 { 00452 fAnnotationBuf.append(chAmpersand); 00453 fAnnotationBuf.append(XMLUni::fgLT); 00454 fAnnotationBuf.append(chSemiColon); 00455 } 00456 else { 00457 fAnnotationBuf.append(chars[i]); 00458 } 00459 } 00460 } 00461 } 00462 00463 void XSDDOMParser::docComment(const XMLCh* const comment) 00464 { 00465 if (fAnnotationDepth > -1) 00466 { 00467 fAnnotationBuf.append(XMLUni::fgCommentString); 00468 fAnnotationBuf.append(comment); 00469 fAnnotationBuf.append(chDash); 00470 fAnnotationBuf.append(chDash); 00471 fAnnotationBuf.append(chCloseAngle); 00472 } 00473 } 00474 00475 void XSDDOMParser::startEntityReference(const XMLEntityDecl&) 00476 { 00477 } 00478 00479 void XSDDOMParser::endEntityReference(const XMLEntityDecl&) 00480 { 00481 } 00482 00483 void XSDDOMParser::ignorableWhitespace( const XMLCh* const chars 00484 , const XMLSize_t length 00485 , const bool) 00486 { 00487 // Ignore chars before the root element 00488 if (!fWithinElement || !fIncludeIgnorableWhitespace) 00489 return; 00490 00491 if (fAnnotationDepth > -1) 00492 fAnnotationBuf.append(chars, length); 00493 } 00494 00495 // --------------------------------------------------------------------------- 00496 // XSDDOMParser: Implementation of the XMLErrorReporter interface 00497 // --------------------------------------------------------------------------- 00498 void XSDDOMParser::error(const unsigned int code 00499 , const XMLCh* const msgDomain 00500 , const XMLErrorReporter::ErrTypes errType 00501 , const XMLCh* const errorText 00502 , const XMLCh* const systemId 00503 , const XMLCh* const publicId 00504 , const XMLFileLoc lineNum 00505 , const XMLFileLoc colNum) 00506 { 00507 if (errType >= XMLErrorReporter::ErrType_Fatal) 00508 fSawFatal = true; 00509 00510 if (fUserErrorReporter) 00511 fUserErrorReporter->error(code, msgDomain, errType, errorText, 00512 systemId, publicId, lineNum, colNum); 00513 } 00514 00515 InputSource* 00516 XSDDOMParser::resolveEntity(XMLResourceIdentifier* resourceIdentifier) 00517 { 00518 if (fUserEntityHandler) 00519 return fUserEntityHandler->resolveEntity(resourceIdentifier); 00520 00521 return 0; 00522 } 00523 00524 XERCES_CPP_NAMESPACE_END