/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id$ */ // --------------------------------------------------------------------------- // Includes // --------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include XERCES_CPP_NAMESPACE_BEGIN // --------------------------------------------------------------------------- // TraverseSchema: Local declaration // --------------------------------------------------------------------------- // This helper class will handle the parsing of namespace prefixes for a given DOMElement, and its winding back class NamespaceScopeManager { public: NamespaceScopeManager(const DOMElement* const node, SchemaInfo* info, TraverseSchema* traverser) { fScopeAdded=node?traverser->retrieveNamespaceMapping(node):false; fSchemaInfo=info; } ~NamespaceScopeManager() { if(fScopeAdded) fSchemaInfo->getNamespaceScope()->decreaseDepth(); } protected: bool fScopeAdded; SchemaInfo* fSchemaInfo; }; // --------------------------------------------------------------------------- // TraverseSchema: Static member data // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // TraverseSchema: Local const data // --------------------------------------------------------------------------- static const XMLCh fgAnonSNamePrefix[] = { chUnderscore, chUnderscore, chLatin_A, chLatin_n, chLatin_o, chLatin_n, chLatin_S, chNull }; static const XMLCh fgAnonCNamePrefix[] = { chUnderscore, chUnderscore, chLatin_A, chLatin_n, chLatin_o, chLatin_n, chLatin_C, chNull }; static const XMLCh fgUnbounded[] = { chLatin_u, chLatin_n, chLatin_b, chLatin_o, chLatin_u, chLatin_n, chLatin_d, chLatin_e, chLatin_d, chNull }; static const XMLCh fgValueOne[] = { chDigit_1, chNull }; static const XMLCh fgValueZero[] = { chDigit_0, chNull }; static const XMLCh* fgIdentityConstraints[] = { SchemaSymbols::fgELT_UNIQUE, SchemaSymbols::fgELT_KEY, SchemaSymbols::fgELT_KEYREF }; static const XMLCh fgSynthetic_Annotation[] = { chLatin_S, chLatin_y, chLatin_n, chLatin_t, chLatin_h, chLatin_e, chLatin_t , chLatin_i, chLatin_c, chUnderscore , chLatin_A, chLatin_n, chLatin_n, chLatin_o, chLatin_t, chLatin_a, chLatin_t , chLatin_i, chLatin_o, chLatin_n, chNull }; // Flags for global declaration enum { ENUM_ELT_SIMPLETYPE, ENUM_ELT_COMPLEXTYPE, ENUM_ELT_ELEMENT, ENUM_ELT_ATTRIBUTE, ENUM_ELT_ATTRIBUTEGROUP, ENUM_ELT_GROUP, ENUM_ELT_SIZE }; typedef JanitorMemFunCall CleanupType; // --------------------------------------------------------------------------- // TraverseSchema: Constructors and Destructor // --------------------------------------------------------------------------- TraverseSchema::TraverseSchema( DOMElement* const schemaRoot , XMLStringPool* const uriStringPool , SchemaGrammar* const schemaGrammar , GrammarResolver* const grammarResolver , RefHash2KeysTableOf* cachedSchemaInfoList , RefHash2KeysTableOf* schemaInfoList , XMLScanner* const xmlScanner , const XMLCh* const schemaURL , XMLEntityHandler* const entityHandler , XMLErrorReporter* const errorReporter , MemoryManager* const manager , bool multipleImport) : fFullConstraintChecking(false) , fTargetNSURI(-1) , fEmptyNamespaceURI(-1) , fCurrentScope(Grammar::TOP_LEVEL_SCOPE) , fScopeCount(schemaGrammar->getScopeCount ()) , fAnonXSTypeCount(schemaGrammar->getAnonTypeCount ()) , fCircularCheckIndex(0) , fTargetNSURIString(0) , fDatatypeRegistry(0) , fGrammarResolver(grammarResolver) , fSchemaGrammar(schemaGrammar) , fEntityHandler(entityHandler) , fErrorReporter(errorReporter) , fURIStringPool(uriStringPool) , fStringPool(0) , fBuffer(1023, manager) , fScanner(xmlScanner) , fAttributeDeclRegistry(0) , fComplexTypeRegistry(0) , fGroupRegistry(0) , fAttGroupRegistry(0) , fIC_ElementsNS(0) , fPreprocessedNodes(0) , fSchemaInfo(0) , fCurrentGroupInfo(0) , fCurrentAttGroupInfo(0) , fCurrentComplexType(0) , fCurrentTypeNameStack(0) , fCurrentGroupStack(0) , fIC_Elements(0) , fDeclStack(0) , fGlobalDeclarations(0) , fNonXSAttList(0) , fImportedNSList(0) , fIC_NodeListNS(0) , fNotationRegistry(0) , fRedefineComponents(0) , fIdentityConstraintNames(0) , fValidSubstitutionGroups(0) , fSchemaInfoList(schemaInfoList) , fCachedSchemaInfoList (cachedSchemaInfoList) , fParser(0) , fLocator(0) , fMemoryManager(manager) , fGrammarPoolMemoryManager(fGrammarResolver->getGrammarPoolMemoryManager()) , fAnnotation(0) , fAttributeCheck(manager) { CleanupType cleanup(this, &TraverseSchema::cleanUp); try { if (fGrammarResolver && schemaRoot && fURIStringPool) { init(); if (multipleImport) { // If we are working on an existing schema, do some // intitialization that is otherwise done by preprocessSchema. // fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry(); fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry(); fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry(); fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry(); fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups(); } preprocessSchema(schemaRoot, schemaURL, multipleImport); doTraverseSchema(schemaRoot); // Store the scope and anon type counts in case we need to add // more to this grammar (multi-import case). schemaGrammar and // fSchemaGrammar should be the same here. // fSchemaGrammar->setScopeCount (fScopeCount); fSchemaGrammar->setAnonTypeCount (fAnonXSTypeCount); } } catch(const OutOfMemoryException&) { cleanup.release(); throw; } cleanup.release(); } TraverseSchema::~TraverseSchema() { cleanUp(); } // --------------------------------------------------------------------------- // TraverseSchema: Traversal methods // --------------------------------------------------------------------------- void TraverseSchema::doTraverseSchema(const DOMElement* const schemaRoot) { // process children nodes processChildren(schemaRoot); // Handle identity constraints - keyref if (fIC_ElementsNS && fIC_ElementsNS->containsKey(fTargetNSURIString)) { fIC_Elements = fIC_ElementsNS->get(fTargetNSURIString); XMLSize_t icListSize = fIC_Elements->size(); for (XMLSize_t i=0; i < icListSize; i++) { SchemaElementDecl* curElem = fIC_Elements->elementAt(i); ValueVectorOf* icNodes = fIC_NodeListNS->get(curElem); XMLSize_t icNodesSize = icNodes->size(); for (XMLSize_t j = 0; j < icNodesSize; j++) { traverseKeyRef(icNodes->elementAt(j), curElem); } } } if (fScanner->getValidateAnnotations() && !fSchemaGrammar->getAnnotations()->isEmpty()) { validateAnnotations(); } fSchemaInfo->setProcessed(); } void TraverseSchema::preprocessSchema(DOMElement* const schemaRoot, const XMLCh* const schemaURL, bool multipleImport) { if (!multipleImport) { // Make sure namespace binding is defaulted const XMLCh* rootPrefix = schemaRoot->getPrefix(); if (rootPrefix == 0 || !*rootPrefix) { const XMLCh* xmlnsStr = schemaRoot->getAttribute(XMLUni::fgXMLNSString); if (!xmlnsStr || !*xmlnsStr) { schemaRoot->setAttribute(XMLUni::fgXMLNSString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA); } } // Set schemaGrammar data and add it to GrammarResolver // For complex type registry, attribute decl registry , group/attGroup // and namespace mapping, needs to check whether the passed in // Grammar was a newly instantiated one. fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry(); if (fComplexTypeRegistry == 0 ) { fComplexTypeRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf(29, fGrammarPoolMemoryManager); fSchemaGrammar->setComplexTypeRegistry(fComplexTypeRegistry); } fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry(); if (fGroupRegistry == 0 ) { fGroupRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf(13, fGrammarPoolMemoryManager); fSchemaGrammar->setGroupInfoRegistry(fGroupRegistry); } fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry(); if (fAttGroupRegistry == 0 ) { fAttGroupRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf(13, fGrammarPoolMemoryManager); fSchemaGrammar->setAttGroupInfoRegistry(fAttGroupRegistry); } fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry(); if (fAttributeDeclRegistry == 0) { fAttributeDeclRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf(29, fGrammarPoolMemoryManager); fSchemaGrammar->setAttributeDeclRegistry(fAttributeDeclRegistry); } fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups(); if (!fValidSubstitutionGroups) { fValidSubstitutionGroups = new (fGrammarPoolMemoryManager) RefHash2KeysTableOf(29, fGrammarPoolMemoryManager); fSchemaGrammar->setValidSubstitutionGroups(fValidSubstitutionGroups); } //Retrieve the targetnamespace URI information const XMLCh* targetNSURIStr = schemaRoot->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); fSchemaGrammar->setTargetNamespace(targetNSURIStr); fCurrentScope = Grammar::TOP_LEVEL_SCOPE; fTargetNSURIString = fSchemaGrammar->getTargetNamespace(); fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString); XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) fSchemaGrammar->getGrammarDescription(); gramDesc->setTargetNamespace(fTargetNSURIString); fGrammarResolver->putGrammar(fSchemaGrammar); } else { fCurrentScope = Grammar::TOP_LEVEL_SCOPE; fTargetNSURIString = fSchemaGrammar->getTargetNamespace(); fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString); } SchemaInfo* currInfo = new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI, 0, schemaURL, fTargetNSURIString, schemaRoot, fScanner, fGrammarPoolMemoryManager); currInfo->getNamespaceScope()->reset(fEmptyNamespaceURI); // Add mapping for the xml prefix currInfo->getNamespaceScope()->addPrefix(XMLUni::fgXMLString, fURIStringPool->addOrFind(XMLUni::fgXMLURIName)); if (fSchemaInfo) fSchemaInfo->addSchemaInfo(currInfo, SchemaInfo::IMPORT); addImportedNS(currInfo->getTargetNSURI()); fSchemaInfo = currInfo; fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), fSchemaInfo->getTargetNSURI(), fSchemaInfo); fSchemaInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE); traverseSchemaHeader(schemaRoot); // preprocess chidren preprocessChildren(schemaRoot); } void TraverseSchema::traverseSchemaHeader(const DOMElement* const schemaRoot) { // Make sure that the root element is if (!XMLString::equals(schemaRoot->getLocalName(), SchemaSymbols::fgELT_SCHEMA)) { reportSchemaError(schemaRoot, XMLUni::fgXMLErrDomain, XMLErrs::InvalidXMLSchemaRoot); } // Make sure that the targetNamespace value is not empty string checkForEmptyTargetNamespace(schemaRoot); // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( schemaRoot, GeneralAttributeCheck::E_Schema, this , true, fSchemaInfo->getNonXSAttList() ); retrieveNamespaceMapping(schemaRoot); // Add mapping for the default namespace if ((!fTargetNSURIString || !*fTargetNSURIString) && schemaRoot->getAttributeNode(XMLUni::fgXMLNSString)==NULL) fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgZeroLenString, fEmptyNamespaceURI); unsigned short elemAttrDefaultQualified = 0; if (XMLString::equals(schemaRoot->getAttribute(SchemaSymbols::fgATT_ELEMENTFORMDEFAULT), SchemaSymbols::fgATTVAL_QUALIFIED)) { elemAttrDefaultQualified |= Elem_Def_Qualified; } if (XMLString::equals(schemaRoot->getAttribute(SchemaSymbols::fgATT_ATTRIBUTEFORMDEFAULT), SchemaSymbols::fgATTVAL_QUALIFIED)) { elemAttrDefaultQualified |= Attr_Def_Qualified; } fSchemaInfo->setElemAttrDefaultQualified(elemAttrDefaultQualified); fSchemaInfo->setBlockDefault(parseBlockSet(schemaRoot, ES_Block, true)); fSchemaInfo->setFinalDefault(parseFinalSet(schemaRoot, ECS_Final, true)); } XSAnnotation* TraverseSchema::traverseAnnotationDecl(const DOMElement* const annotationElem, ValueVectorOf* const nonXSAttList, const bool topLevel) { NamespaceScopeManager nsMgr(annotationElem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( annotationElem, GeneralAttributeCheck::E_Annotation, this, topLevel ); const XMLCh* contents = 0; DOMElement* child = XUtil::getFirstChildElement(annotationElem); if (child) { for (; child != 0; child = XUtil::getNextSiblingElement(child)) { const XMLCh* name = child->getLocalName(); if (XMLString::equals(name, SchemaSymbols::fgELT_APPINFO)) { DOMNode* textContent = child->getFirstChild(); if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE) contents = ((DOMText*) textContent)->getData(); fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::E_Appinfo, this); } else if (XMLString::equals(name, SchemaSymbols::fgELT_DOCUMENTATION)) { DOMNode* textContent = child->getFirstChild(); if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE) contents = ((DOMText*) textContent)->getData(); fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::E_Documentation, this); } else { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAnnotationContent); } } } else { // If the Annotation has no children, get the text directly DOMNode* textContent = annotationElem->getFirstChild(); if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE) contents = ((DOMText*) textContent)->getData(); } if (contents && !fScanner->getIgnoreAnnotations()) { XSAnnotation* theAnnotation = 0; XMLSize_t nonXSAttSize = nonXSAttList->size(); if (nonXSAttSize) { int annotTokenStart = XMLString::patternMatch( contents, SchemaSymbols::fgELT_ANNOTATION); if (annotTokenStart == -1) // something is wrong return 0; // set annotation element fBuffer.set(contents, annotTokenStart + 10); for (XMLSize_t i=0; ielementAt(i); if (!XMLString::equals( annotationElem->getAttributeNS( attNode->getNamespaceURI(), attNode->getLocalName()) , XMLUni::fgZeroLenString) ) { continue; } fBuffer.append(chSpace); fBuffer.append(attNode->getNodeName()); fBuffer.append(chEqual); fBuffer.append(chDoubleQuote); processAttValue(attNode->getNodeValue(), fBuffer); fBuffer.append(chDoubleQuote); } // add remaining annotation content fBuffer.append(contents + annotTokenStart + 10); theAnnotation = new (fGrammarPoolMemoryManager) XSAnnotation(fBuffer.getRawBuffer(), fGrammarPoolMemoryManager); } else { theAnnotation = new (fGrammarPoolMemoryManager) XSAnnotation(contents, fGrammarPoolMemoryManager); } /*** * set line, col and systemId info ***/ theAnnotation->setLineCol( ((XSDElementNSImpl*)annotationElem)->getLineNo() , ((XSDElementNSImpl*)annotationElem)->getColumnNo() ); theAnnotation->setSystemId(fSchemaInfo->getCurrentSchemaURL()); return theAnnotation; } return 0; } /** * Traverse include * * * Content: (annotation?) * */ void TraverseSchema::preprocessInclude(const DOMElement* const elem) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_Include, this, true, fNonXSAttList); // ----------------------------------------------------------------------- // First, handle any ANNOTATION declaration // ----------------------------------------------------------------------- if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); if (fAnnotation) fSchemaGrammar->addAnnotation(fAnnotation); else if (fScanner->getGenerateSyntheticAnnotations() && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); fSchemaGrammar->addAnnotation(fAnnotation); } // ----------------------------------------------------------------------- // Get 'schemaLocation' attribute // ----------------------------------------------------------------------- const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION, DatatypeValidator::AnyURI); if (!schemaLocation || !*schemaLocation) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNoSchemaLocation, SchemaSymbols::fgELT_INCLUDE); return; } // ------------------------------------------------------------------ // Resolve schema location // ------------------------------------------------------------------ fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, ((XSDElementNSImpl*) elem)->getLineNo(), ((XSDElementNSImpl*) elem)->getColumnNo()); InputSource* srcToFill = resolveSchemaLocation(schemaLocation, XMLResourceIdentifier::SchemaInclude); Janitor janSrc(srcToFill); // Nothing to do if (!srcToFill) { return; } const XMLCh* includeURL = srcToFill->getSystemId(); SchemaInfo* includeSchemaInfo = fCachedSchemaInfoList->get(includeURL, fTargetNSURI); if (!includeSchemaInfo && fSchemaInfoList != fCachedSchemaInfoList) includeSchemaInfo = fSchemaInfoList->get(includeURL, fTargetNSURI); if (includeSchemaInfo) { fSchemaInfo->addSchemaInfo(includeSchemaInfo, SchemaInfo::INCLUDE); return; } // ------------------------------------------------------------------ // Parse input source // ------------------------------------------------------------------ if (!fParser) fParser = new (fGrammarPoolMemoryManager) XSDDOMParser(0, fGrammarPoolMemoryManager, 0); fParser->setValidationScheme(XercesDOMParser::Val_Never); fParser->setDoNamespaces(true); fParser->setUserEntityHandler(fEntityHandler); fParser->setUserErrorReporter(fErrorReporter); // Should just issue warning if the schema is not found bool flag = srcToFill->getIssueFatalErrorIfNotFound(); srcToFill->setIssueFatalErrorIfNotFound(false); fParser->parse(*srcToFill); // Reset the InputSource srcToFill->setIssueFatalErrorIfNotFound(flag); if (fParser->getSawFatal() && fScanner->getExitOnFirstFatal()) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError); // ------------------------------------------------------------------ // Get root element // ------------------------------------------------------------------ DOMDocument* document = fParser->getDocument(); if (document) { DOMElement* root = document->getDocumentElement(); if (root) { const XMLCh* targetNSURIString = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); // check to see if targetNameSpace is right if (*targetNSURIString && !XMLString::equals(targetNSURIString,fTargetNSURIString)){ reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::IncludeNamespaceDifference, schemaLocation, targetNSURIString); return; } // if targetNamespace is empty, change it to includ'g schema // targetNamespace if (!*targetNSURIString && root->getAttributeNode(XMLUni::fgXMLNSString) == 0 && fTargetNSURI != fEmptyNamespaceURI) { root->setAttribute(XMLUni::fgXMLNSString, fTargetNSURIString); } // -------------------------------------------------------- // Update schema information with included schema // -------------------------------------------------------- SchemaInfo* saveInfo = fSchemaInfo; fSchemaInfo = new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI, 0, includeURL, fTargetNSURIString, root, fScanner, fGrammarPoolMemoryManager); fSchemaInfo->getNamespaceScope()->reset(fEmptyNamespaceURI); // Add mapping for the xml prefix fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgXMLString, fURIStringPool->addOrFind(XMLUni::fgXMLURIName)); fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), fSchemaInfo->getTargetNSURI(), fSchemaInfo); fPreprocessedNodes->put((void*) elem, fSchemaInfo); saveInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE); traverseSchemaHeader(root); preprocessChildren(root); fSchemaInfo = saveInfo; } } } void TraverseSchema::traverseInclude(const DOMElement* const elem) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); SchemaInfo* includeInfo = fPreprocessedNodes->get(elem); if (includeInfo) { SchemaInfo* saveInfo = fSchemaInfo; fSchemaInfo = includeInfo; processChildren(includeInfo->getRoot()); fSchemaInfo = saveInfo; } } /** * Traverse import * * * Content: (annotation?) * */ void TraverseSchema::preprocessImport(const DOMElement* const elem) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_Import, this, true, fNonXSAttList); // ----------------------------------------------------------------------- // First, handle any ANNOTATION declaration // ----------------------------------------------------------------------- if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); if (fAnnotation) fSchemaGrammar->addAnnotation(fAnnotation); else if (fScanner->getGenerateSyntheticAnnotations() && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); fSchemaGrammar->addAnnotation(fAnnotation); } // ----------------------------------------------------------------------- // Handle 'namespace' attribute // ----------------------------------------------------------------------- const XMLCh* nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE, DatatypeValidator::AnyURI); const XMLCh* nameSpaceValue = nameSpace ? nameSpace : XMLUni::fgZeroLenString; if (XMLString::equals(nameSpaceValue, fTargetNSURIString)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Import_1_1); return; } if (!*nameSpaceValue && fTargetNSURI == fEmptyNamespaceURI) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Import_1_2); return; } // ------------------------------------------------------------------ // Get 'schemaLocation' attribute // ------------------------------------------------------------------ const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION, DatatypeValidator::AnyURI); // ------------------------------------------------------------------ // Resolve namespace to a grammar // ------------------------------------------------------------------ Grammar* aGrammar = 0; { XMLSchemaDescription* gramDesc =fGrammarResolver->getGrammarPool()->createSchemaDescription(nameSpaceValue); Janitor janName(gramDesc); gramDesc->setContextType(XMLSchemaDescription::CONTEXT_IMPORT); gramDesc->setLocationHints(schemaLocation); aGrammar = fGrammarResolver->getGrammar(gramDesc); } bool grammarFound = (aGrammar && (aGrammar->getGrammarType() == Grammar::SchemaGrammarType)); if (grammarFound) { addImportedNS(fURIStringPool->addOrFind(nameSpaceValue)); } // a bare doesn't load anything if(!schemaLocation && !nameSpace) return; // ------------------------------------------------------------------ // Resolve schema location // ------------------------------------------------------------------ fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, ((XSDElementNSImpl*) elem)->getLineNo(), ((XSDElementNSImpl*) elem)->getColumnNo()); InputSource* srcToFill = resolveSchemaLocation(schemaLocation, XMLResourceIdentifier::SchemaImport, nameSpace); // Nothing to do if (!srcToFill) { if (!grammarFound) { addImportedNS(fURIStringPool->addOrFind(nameSpaceValue)); } return; } Janitor janSrc(srcToFill); const XMLCh* importURL = srcToFill->getSystemId(); unsigned int nameSpaceId = nameSpace ? fURIStringPool->addOrFind(nameSpace) : fEmptyNamespaceURI; SchemaInfo* importSchemaInfo = fCachedSchemaInfoList->get(importURL, nameSpaceId); if (!importSchemaInfo && fSchemaInfoList != fCachedSchemaInfoList) importSchemaInfo = fSchemaInfoList->get(importURL, nameSpaceId); if (importSchemaInfo) { fSchemaInfo->addSchemaInfo(importSchemaInfo, SchemaInfo::IMPORT); addImportedNS(importSchemaInfo->getTargetNSURI()); return; } if (grammarFound) { if (!fScanner->getHandleMultipleImports()) return; } // ------------------------------------------------------------------ // Parse input source // ------------------------------------------------------------------ if (!fParser) fParser = new (fGrammarPoolMemoryManager) XSDDOMParser(0, fGrammarPoolMemoryManager, 0); fParser->setValidationScheme(XercesDOMParser::Val_Never); fParser->setDoNamespaces(true); fParser->setUserEntityHandler(fEntityHandler); fParser->setUserErrorReporter(fErrorReporter); // Should just issue warning if the schema is not found bool flag = srcToFill->getIssueFatalErrorIfNotFound(); srcToFill->setIssueFatalErrorIfNotFound(false); fParser->parse(*srcToFill) ; // Reset the InputSource srcToFill->setIssueFatalErrorIfNotFound(flag); if (fParser->getSawFatal() && fScanner->getExitOnFirstFatal()) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError); // ------------------------------------------------------------------ // Get root element // ------------------------------------------------------------------ DOMDocument* document = fParser->getDocument(); if (document) { DOMElement* root = document->getDocumentElement(); if (!root) { return; } const XMLCh* targetNSURIString = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); if (!XMLString::equals(targetNSURIString, nameSpaceValue)) { reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::ImportNamespaceDifference, schemaLocation, targetNSURIString, nameSpaceValue); } else { // -------------------------------------------------------- // Preprocess new schema // -------------------------------------------------------- SchemaInfo* saveInfo = fSchemaInfo; fSchemaGrammar->setScopeCount (fScopeCount); fSchemaGrammar->setAnonTypeCount (fAnonXSTypeCount); if (grammarFound) { fSchemaGrammar = (SchemaGrammar*) aGrammar; } else { fSchemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager); } fScopeCount = fSchemaGrammar->getScopeCount (); fAnonXSTypeCount = fSchemaGrammar->getAnonTypeCount (); XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) fSchemaGrammar->getGrammarDescription(); gramDesc->setContextType(XMLSchemaDescription::CONTEXT_IMPORT); gramDesc->setLocationHints(importURL); preprocessSchema(root, importURL, grammarFound); fPreprocessedNodes->put((void*) elem, fSchemaInfo); // -------------------------------------------------------- // Restore old schema information // -------------------------------------------------------- restoreSchemaInfo(saveInfo, SchemaInfo::IMPORT); } } } void TraverseSchema::traverseImport(const DOMElement* const elem) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); SchemaInfo* importInfo = fPreprocessedNodes->get(elem); if (importInfo) { // -------------------------------------------------------- // Traverse new schema // -------------------------------------------------------- SchemaInfo* saveInfo = fSchemaInfo; restoreSchemaInfo(importInfo, SchemaInfo::IMPORT); doTraverseSchema(importInfo->getRoot()); // -------------------------------------------------------- // Restore old schema information // -------------------------------------------------------- restoreSchemaInfo(saveInfo, SchemaInfo::IMPORT); } } /** * Traverse redefine declaration * * * schemaLocation = uriReference * {any attributes with non-schema namespace . . .}> * Content: (annotation | ( * attributeGroup | complexType | group | simpleType))* * */ void TraverseSchema::preprocessRedefine(const DOMElement* const redefineElem) { NamespaceScopeManager nsMgr(redefineElem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( redefineElem, GeneralAttributeCheck::E_Redefine, this, true ); // First, we look through the children of redefineElem. Each one will // correspond to an element of the redefined schema that we need to // redefine. To do this, we rename the element of the redefined schema, // and rework the base or ref tag of the kid we're working on to refer to // the renamed group or derive the renamed type. Once we've done this, we // actually go through the schema being redefined and convert it to a // grammar. Only then do we run through redefineDecl's kids and put them // in the grammar. SchemaInfo* redefiningInfo = fSchemaInfo; if (!openRedefinedSchema(redefineElem)) { redefiningInfo->addFailedRedefine(redefineElem); return; } if (!fRedefineComponents) { fRedefineComponents = new (fMemoryManager) RefHash2KeysTableOf(13, (bool) false, fMemoryManager); } SchemaInfo* redefinedInfo = fSchemaInfo; renameRedefinedComponents(redefineElem, redefiningInfo, redefinedInfo); // Now we have to preprocess our nicely-renamed schemas. if (fPreprocessedNodes->containsKey(redefineElem)) { fSchemaInfo = redefinedInfo; preprocessChildren(fSchemaInfo->getRoot()); } fSchemaInfo = redefiningInfo; } void TraverseSchema::traverseRedefine(const DOMElement* const redefineElem) { NamespaceScopeManager nsMgr(redefineElem, fSchemaInfo, this); SchemaInfo* saveInfo = fSchemaInfo; SchemaInfo* redefinedInfo = fPreprocessedNodes->get(redefineElem); if (redefinedInfo) { // Now we have to march through our nicely-renamed schemas. When // we do these traversals other 's may perhaps be // encountered; we leave recursion to sort this out. fSchemaInfo = redefinedInfo; processChildren(fSchemaInfo->getRoot()); fSchemaInfo = saveInfo; // Now traverse our own processChildren(redefineElem); } } /** * Traverse the Choice, Sequence declaration * * */ ContentSpecNode* TraverseSchema::traverseChoiceSequence(const DOMElement* const elem, const int modelGroupType, bool& hasChildren) { hasChildren = false; NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_Sequence, this, false, fNonXSAttList ); // ----------------------------------------------------------------------- // Process contents // ----------------------------------------------------------------------- DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } Janitor janAnnot(fAnnotation); Janitor left(0); Janitor right(0); bool hadContent = false; Janitor contentSpecNode(0); for (; child != 0; child = XUtil::getNextSiblingElement(child)) { hasChildren = true; contentSpecNode.release(); bool seeParticle = false; bool wasAny = false; const XMLCh* childName = child->getLocalName(); if (XMLString::equals(childName, SchemaSymbols::fgELT_ELEMENT)) { SchemaElementDecl* elemDecl = traverseElementDecl(child); if (!elemDecl ) continue; contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode ( elemDecl , fGrammarPoolMemoryManager )); seeParticle = true; } else if (XMLString::equals(childName, SchemaSymbols::fgELT_GROUP)) { XercesGroupInfo* grpInfo = traverseGroupDecl(child, false); if (!grpInfo) { continue; } ContentSpecNode* grpContentSpecNode = grpInfo->getContentSpec(); if (!grpContentSpecNode) { continue; } if (grpContentSpecNode->hasAllContent()) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AllContentLimited); continue; } contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode(*grpContentSpecNode)); seeParticle = true; } else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) { bool hasChild; contentSpecNode.reset(traverseChoiceSequence(child,ContentSpecNode::Choice, hasChild)); seeParticle = true; } else if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) { bool hasChild; contentSpecNode.reset(traverseChoiceSequence(child,ContentSpecNode::Sequence, hasChild)); seeParticle = true; } else if (XMLString::equals(childName, SchemaSymbols::fgELT_ANY)) { contentSpecNode.reset(traverseAny(child)); seeParticle = true; wasAny = true; } else { reportSchemaError(child, XMLUni::fgValidityDomain, XMLValid::GroupContentRestricted, childName, ((ContentSpecNode::NodeTypes) modelGroupType) == ContentSpecNode::Choice?SchemaSymbols::fgELT_CHOICE:SchemaSymbols::fgELT_SEQUENCE); } if (seeParticle) { checkMinMax(contentSpecNode.get(), child, Not_All_Context); if (wasAny && contentSpecNode.get()->getMaxOccurs() == 0) { contentSpecNode.reset(0); } } if (contentSpecNode.get()) { hadContent = true; } if (left.get() == 0) { left.reset(contentSpecNode.release()); } else if (right.get() == 0) { right.reset(contentSpecNode.release()); } else { ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( (ContentSpecNode::NodeTypes) modelGroupType , left.get() , right.get() , true , true , fGrammarPoolMemoryManager ); left.release(); right.release(); left.reset(newNode); right.reset(contentSpecNode.release()); } } contentSpecNode.release(); if (hadContent) { ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( ((ContentSpecNode::NodeTypes) modelGroupType) == ContentSpecNode::Choice ? ContentSpecNode::ModelGroupChoice : ContentSpecNode::ModelGroupSequence , left.get() , right.get() , true , true , fGrammarPoolMemoryManager ); left.release(); left.reset(newNode); if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(left.get(), janAnnot.release()); } right.release(); return left.release(); } /** * Traverse SimpleType declaration: * * Content: (annotation? , ((list | restriction | union))) * * * traverse || */ DatatypeValidator* TraverseSchema::traverseSimpleTypeDecl(const DOMElement* const childElem, const bool topLevel, int baseRefContext) { NamespaceScopeManager nsMgr(childElem, fSchemaInfo, this); // ------------------------------------------------------------------ // Process contents // ------------------------------------------------------------------ const XMLCh* name = getElementAttValue(childElem,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); bool nameEmpty = (!name || !*name); if (topLevel && nameEmpty) { reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement, SchemaSymbols::fgELT_SIMPLETYPE); return 0; } else if(!topLevel && !nameEmpty) { reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeDisallowedLocal, SchemaSymbols::fgATT_NAME, childElem->getLocalName()); return 0; } if (nameEmpty) { // anonymous simpleType name = genAnonTypeName(fgAnonSNamePrefix); } else if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) ) { reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_SIMPLETYPE, name); return 0; } fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(name); unsigned int fullTypeNameId = fStringPool->addOrFind(fBuffer.getRawBuffer()); const XMLCh* fullName = fStringPool->getValueForId(fullTypeNameId); //check if we have already traversed the same simpleType decl DatatypeValidator* dv = fDatatypeRegistry->getDatatypeValidator(fullName); if (!dv) { // ------------------------------------------------------------------- // Check attributes // ------------------------------------------------------------------- unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_SimpleTypeGlobal : GeneralAttributeCheck::E_SimpleTypeLocal; fAttributeCheck.checkAttributes( childElem, scope, this, topLevel, fNonXSAttList ); // Circular constraint checking if (fCurrentTypeNameStack->containsElement(fullTypeNameId)) { reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, name); return 0; } fCurrentTypeNameStack->addElement(fullTypeNameId); // Get 'final' values int finalSet = parseFinalSet(childElem, S_Final); // annotation?,(list|restriction|union) DOMElement* content= checkContent( childElem, XUtil::getFirstChildElement(childElem), false); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(childElem, fNonXSAttList); } Janitor janAnnot(fAnnotation); if (content == 0) { reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent); popCurrentTypeNameStack(); return 0; } const XMLCh* varietyName = content->getLocalName(); // Remark: some code will be repeated in list|restriction| union but it // is cleaner that way if (XMLString::equals(varietyName, SchemaSymbols::fgELT_LIST)) { //traverse List if ((baseRefContext & SchemaSymbols::XSD_LIST) != 0) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AtomicItemType); popCurrentTypeNameStack(); return 0; } dv = traverseByList(childElem, content, name, fullName, finalSet, &janAnnot); } else if (XMLString::equals(varietyName, SchemaSymbols::fgELT_RESTRICTION)) { //traverse Restriction dv = traverseByRestriction(childElem, content, name, fullName, finalSet, &janAnnot); } else if (XMLString::equals(varietyName, SchemaSymbols::fgELT_UNION)) { //traverse union dv = traverseByUnion(childElem, content, name, fullName, finalSet, baseRefContext, &janAnnot); } else { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::FeatureUnsupported, varietyName); popCurrentTypeNameStack(); } if (dv) { if (nameEmpty) dv->setAnonymous(); if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(dv, janAnnot.release()); } } return dv; } /** * Traverse ComplexType Declaration - CR Implementation. * * * Content: (annotation? , (simpleContent | complexContent | * ( (group | all | choice | sequence)? , * ( (attribute | attributeGroup)* , anyAttribute?)))) * */ int TraverseSchema::traverseComplexTypeDecl(const DOMElement* const elem, const bool topLevel, const XMLCh* const recursingTypeName) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // Get the attributes of the complexType const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); bool isAnonymous = false; if (!name || !*name) { if (topLevel) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameComplexType); return -1; } if (recursingTypeName) name = recursingTypeName; else { name = genAnonTypeName(fgAnonCNamePrefix); isAnonymous = true; } } if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) ) { //REVISIT - Should we return or continue and save type with wrong name? reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_COMPLEXTYPE, name); return -1; } // ------------------------------------------------------------------ // Check if the type has already been registered // ------------------------------------------------------------------ fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(name); int typeNameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); const XMLCh* fullName = fStringPool->getValueForId(typeNameIndex); ComplexTypeInfo* typeInfo = 0; if (topLevel || recursingTypeName) { typeInfo = fComplexTypeRegistry->get(fullName); if (typeInfo && !typeInfo->getPreprocessed()) { return typeNameIndex; } } // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- bool preProcessFlag = (typeInfo) ? typeInfo->getPreprocessed() : false; if (!preProcessFlag) { fAttributeCheck.checkAttributes( elem, (topLevel) ? GeneralAttributeCheck::E_ComplexTypeGlobal : GeneralAttributeCheck::E_ComplexTypeLocal , this, topLevel, fNonXSAttList ); } // ----------------------------------------------------------------------- // Create a new instance // ----------------------------------------------------------------------- XMLSize_t previousCircularCheckIndex = fCircularCheckIndex; unsigned int previousScope = fCurrentScope; if (preProcessFlag) { fCurrentScope = typeInfo->getScopeDefined(); typeInfo->setPreprocessed(false); } else { // ------------------------------------------------------------------ // Register the type // ------------------------------------------------------------------ typeInfo = new (fGrammarPoolMemoryManager) ComplexTypeInfo(fGrammarPoolMemoryManager); if(isAnonymous) { typeInfo->setAnonymous(); } fCurrentScope = fScopeCount++; fComplexTypeRegistry->put((void*) fullName, typeInfo); typeInfo->setTypeName(fullName); typeInfo->setScopeDefined(fCurrentScope); if (fFullConstraintChecking) { XSDLocator* aLocator = new (fGrammarPoolMemoryManager) XSDLocator(); aLocator->setValues(fStringPool->getValueForId(fStringPool->addOrFind(fSchemaInfo->getCurrentSchemaURL())), 0, ((XSDElementNSImpl*) elem)->getLineNo(), ((XSDElementNSImpl*) elem)->getColumnNo()); typeInfo->setLocator(aLocator); } } fCurrentTypeNameStack->addElement(typeNameIndex); ComplexTypeInfo* saveTypeInfo = fCurrentComplexType; fCurrentComplexType = typeInfo; // ------------------------------------------------------------------ // First, handle any ANNOTATION declaration and get next child // ------------------------------------------------------------------ DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true, !preProcessFlag); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } Janitor janAnnot(fAnnotation); // ------------------------------------------------------------------ // Process the content of the complex type declaration // ------------------------------------------------------------------ try { const XMLCh* mixedVal = getElementAttValue(elem,SchemaSymbols::fgATT_MIXED, DatatypeValidator::Boolean); bool isMixed = false; if ((mixedVal && *mixedVal) && (XMLString::equals(SchemaSymbols::fgATTVAL_TRUE, mixedVal) || XMLString::equals(fgValueOne, mixedVal))) { isMixed = true; } if (child == 0) { // EMPTY complexType with complexContent processComplexContent(elem, name, child, typeInfo, 0, isMixed); } else { const XMLCh* childName = child->getLocalName(); if (XMLString::equals(childName, SchemaSymbols::fgELT_SIMPLECONTENT)) { // SIMPLE CONTENT element traverseSimpleContentDecl(name, fullName, child, typeInfo, &janAnnot); if (XUtil::getNextSiblingElement(child) != 0) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingSimpleContent); } } else if (XMLString::equals(childName, SchemaSymbols::fgELT_COMPLEXCONTENT)) { // COMPLEX CONTENT element traverseComplexContentDecl(name, child, typeInfo, isMixed, &janAnnot); if (XUtil::getNextSiblingElement(child) != 0) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingConplexContent); } } else if (fCurrentGroupInfo) { typeInfo->setPreprocessed(true); } else { // We must have .... // GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes // Note that it's possible that only attributes are specified. processComplexContent(elem, name, child, typeInfo, 0, isMixed); } } } catch(const TraverseSchema::ExceptionCodes aCode) { if (aCode == TraverseSchema::InvalidComplexTypeInfo) defaultComplexTypeInfo(typeInfo); else if (aCode == TraverseSchema::RecursingElement) typeInfo->setPreprocessed(); } // ------------------------------------------------------------------ // Finish the setup of the typeInfo // ------------------------------------------------------------------ if (!preProcessFlag) { const XMLCh* abstractAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT, DatatypeValidator::Boolean); int blockSet = parseBlockSet(elem, C_Block); int finalSet = parseFinalSet(elem, EC_Final); typeInfo->setBlockSet(blockSet); typeInfo->setFinalSet(finalSet); if ((abstractAttVal && *abstractAttVal) && (XMLString::equals(abstractAttVal, SchemaSymbols::fgATTVAL_TRUE) || XMLString::equals(abstractAttVal, fgValueOne))) { typeInfo->setAbstract(true); } else { typeInfo->setAbstract(false); } } // Store Annotation if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(typeInfo, janAnnot.release()); // ------------------------------------------------------------------ // Before exiting, restore the scope, mainly for nested anonymous types // ------------------------------------------------------------------ popCurrentTypeNameStack(); fCircularCheckIndex = previousCircularCheckIndex; fCurrentScope = previousScope; fCurrentComplexType = saveTypeInfo; return typeNameIndex; } /** * Traverse Group Declaration. * * * Content: (annotation? , (all | choice | sequence)?) * * */ XercesGroupInfo* TraverseSchema::traverseGroupDecl(const DOMElement* const elem, const bool topLevel) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); bool nameEmpty = (!name || !*name); bool refEmpty = (!ref || !*ref); if (nameEmpty && topLevel) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement, SchemaSymbols::fgELT_GROUP); return 0; } if (nameEmpty && refEmpty) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefGroup); return 0; } // ------------------------------------------------------------------ // Check attributes // ------------------------------------------------------------------ unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_GroupGlobal : GeneralAttributeCheck::E_GroupRef; fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList); // ------------------------------------------------------------------ // Handle "ref=" // ------------------------------------------------------------------ if (!topLevel) { if (refEmpty) { return 0; } return processGroupRef(elem, ref); } // name must be a valid NCName if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_GROUP, name); return 0; } fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(name); unsigned int nameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); const XMLCh* fullName = fStringPool->getValueForId(nameIndex); XercesGroupInfo* groupInfo = fGroupRegistry->get(fullName); if (groupInfo) { return groupInfo; } // ------------------------------------------------------------------ // Check for annotations // ------------------------------------------------------------------ DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } Janitor janAnnot(fAnnotation); // ------------------------------------------------------------------ // Process contents of global groups // ------------------------------------------------------------------ unsigned int saveScope = fCurrentScope; Janitor specNode(0); XercesGroupInfo* saveGroupInfo = fCurrentGroupInfo; Janitor newGroupInfoJan(new (fGrammarPoolMemoryManager) XercesGroupInfo( fStringPool->addOrFind(name), fTargetNSURI, fGrammarPoolMemoryManager)); fCurrentGroupStack->addElement(nameIndex); XercesGroupInfo* const newGroupInfo = newGroupInfoJan.get(); fCurrentGroupInfo = newGroupInfo; fCurrentScope = fScopeCount++; fCurrentGroupInfo->setScope(fCurrentScope); if (content == 0) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::GroupContentError, name); } else { if (content->getAttributeNode(SchemaSymbols::fgATT_MINOCCURS) != 0 || content->getAttributeNode(SchemaSymbols::fgATT_MAXOCCURS) != 0) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::MinMaxOnGroupChild); } bool illegalChild = false; const XMLCh* childName = content->getLocalName(); bool hasChild; if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) { specNode.reset(traverseChoiceSequence(content, ContentSpecNode::Sequence, hasChild)); } else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) { specNode.reset(traverseChoiceSequence(content, ContentSpecNode::Choice, hasChild)); } else if (XMLString::equals(childName, SchemaSymbols::fgELT_ALL)) { specNode.reset(traverseAll(content, hasChild)); } else { illegalChild = true; } if (illegalChild || XUtil::getNextSiblingElement(content) != 0) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::GroupContentError, name); } // copy local elements to complex type if it exists if (fCurrentComplexType) processElements(elem, fCurrentGroupInfo, fCurrentComplexType); } // ------------------------------------------------------------------ // Set groupInfo and pop group name from stack // ------------------------------------------------------------------ XMLSize_t stackSize = fCurrentGroupStack->size(); if (stackSize != 0) { fCurrentGroupStack->removeElementAt(stackSize - 1); } fCurrentGroupInfo->setContentSpec(specNode.release()); fGroupRegistry->put((void*) fullName, fCurrentGroupInfo); newGroupInfoJan.release(); fCurrentGroupInfo = saveGroupInfo; fCurrentScope = saveScope; // Store Annotation if (!janAnnot.isDataNull()) { fSchemaGrammar->putAnnotation(newGroupInfo, janAnnot.release()); } if (fFullConstraintChecking) { XSDLocator* aLocator = new (fGrammarPoolMemoryManager) XSDLocator(); newGroupInfo->setLocator(aLocator); aLocator->setValues(fStringPool->getValueForId(fStringPool->addOrFind(fSchemaInfo->getCurrentSchemaURL())), 0, ((XSDElementNSImpl*) elem)->getLineNo(), ((XSDElementNSImpl*) elem)->getColumnNo()); if (fRedefineComponents && fRedefineComponents->get(SchemaSymbols::fgELT_GROUP, nameIndex)) { fBuffer.set(fullName); fBuffer.append(SchemaSymbols::fgRedefIdentifier); unsigned int rdfNameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); if (fCurrentGroupStack->containsElement(rdfNameIndex)) { reportSchemaError(aLocator, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, name); } else { XercesGroupInfo* baseGroup = fGroupRegistry->get(fBuffer.getRawBuffer()); if (baseGroup) { newGroupInfo->setBaseGroup(baseGroup); } else { fBuffer.set(name); fBuffer.append(SchemaSymbols::fgRedefIdentifier); SchemaInfo* saveInfo = fSchemaInfo; DOMElement* groupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Group, SchemaSymbols::fgELT_GROUP, fBuffer.getRawBuffer(), &fSchemaInfo); if (groupElem != 0) { baseGroup = traverseGroupDecl(groupElem); newGroupInfo->setBaseGroup(baseGroup); fSchemaInfo = saveInfo; } else { reportSchemaError(aLocator, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, SchemaSymbols::fgELT_GROUP, fTargetNSURIString, fBuffer.getRawBuffer()); } } } } } return newGroupInfo; } /** * Traverse attributeGroup Declaration. * * * Content: (annotation? , (attribute|attributeGroup)*, anyAttribute?) * * */ XercesAttGroupInfo* TraverseSchema::traverseAttributeGroupDecl(const DOMElement* const elem, ComplexTypeInfo* const typeInfo, const bool topLevel) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); bool nameEmpty = (!name || !*name) ? true : false; bool refEmpty = (!ref || !*ref) ? true : false; if (nameEmpty && topLevel) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement, SchemaSymbols::fgELT_ATTRIBUTEGROUP); return 0; } if (nameEmpty && refEmpty) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttGroup); return 0; } // ------------------------------------------------------------------ // Check attributes // ------------------------------------------------------------------ unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_AttributeGroupGlobal : GeneralAttributeCheck::E_AttributeGroupRef; fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList); // ------------------------------------------------------------------ // Handle "ref=" // ------------------------------------------------------------------ XercesAttGroupInfo* attGroupInfo; Janitor janAttGroupInfo(0); if (!topLevel) { if (refEmpty) { return 0; } attGroupInfo = processAttributeGroupRef(elem, ref, typeInfo); } else { // name must be a valid NCName if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ATTRIBUTEGROUP, name); return 0; } // Check for annotations DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } Janitor janAnnot(fAnnotation); // Process contents of global attributeGroups XercesAttGroupInfo* saveAttGroupInfo = fCurrentAttGroupInfo; janAttGroupInfo.reset(new (fGrammarPoolMemoryManager) XercesAttGroupInfo( fStringPool->addOrFind(name), fTargetNSURI, fGrammarPoolMemoryManager)); fDeclStack->addElement(elem); fCurrentAttGroupInfo = janAttGroupInfo.get(); for (; content !=0; content = XUtil::getNextSiblingElement(content)) { if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ATTRIBUTE)) { traverseAttributeDecl(content, typeInfo); } else if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ATTRIBUTEGROUP)) { traverseAttributeGroupDecl(content, typeInfo); } else { break; } } if (content != 0) { if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ANYATTRIBUTE)) { SchemaAttDef* anyAtt = traverseAnyAttribute(content); if (anyAtt) { fCurrentAttGroupInfo->addAnyAttDef(anyAtt); } if (XUtil::getNextSiblingElement(content) != 0) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AttGroupContentError, name); } } else { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AttGroupContentError, name); } } // Pop declaration fDeclStack->removeElementAt(fDeclStack->size() - 1); fAttGroupRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), janAttGroupInfo.get()); // Restore old attGroupInfo attGroupInfo = janAttGroupInfo.release(); fCurrentAttGroupInfo = saveAttGroupInfo; // Check Attribute Derivation Restriction OK fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(name); unsigned int nameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); if (fRedefineComponents && fRedefineComponents->get(SchemaSymbols::fgELT_ATTRIBUTEGROUP, nameIndex)) { fBuffer.set(name); fBuffer.append(SchemaSymbols::fgRedefIdentifier); XercesAttGroupInfo* baseAttGroupInfo = fAttGroupRegistry->get(fBuffer.getRawBuffer()); if (baseAttGroupInfo) checkAttDerivationOK(elem, baseAttGroupInfo, attGroupInfo); } // Store annotation if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(attGroupInfo, janAnnot.release()); } // calculate complete wildcard if necessary if (attGroupInfo) { XMLSize_t anyAttCount = attGroupInfo->anyAttributeCount(); if (anyAttCount && !attGroupInfo->getCompleteWildCard()) { SchemaAttDef* attGroupWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(attGroupInfo->anyAttributeAt(0)); for (XMLSize_t k= 1; k < anyAttCount; k++) attWildCardIntersection(attGroupWildCard, attGroupInfo->anyAttributeAt(k)); attGroupInfo->setCompleteWildCard(attGroupWildCard); } } return attGroupInfo; } inline XercesAttGroupInfo* TraverseSchema::traverseAttributeGroupDeclNS(const DOMElement* const elem, const XMLCh* const uriStr, const XMLCh* const name) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // ------------------------------------------------------------------ // Get grammar information // ------------------------------------------------------------------ Grammar* aGrammar = fGrammarResolver->getGrammar(uriStr); if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); return 0; } XercesAttGroupInfo* attGroupInfo = ((SchemaGrammar*)aGrammar)->getAttGroupInfoRegistry()->get(name); return attGroupInfo; } /** * Traverse Any declaration * * * Content: (annotation?) * */ ContentSpecNode* TraverseSchema::traverseAny(const DOMElement* const elem) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_Any, this, false, fNonXSAttList ); // ------------------------------------------------------------------ // First, handle any ANNOTATION declaration // ------------------------------------------------------------------ if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } Janitor janAnnot(fAnnotation); // ------------------------------------------------------------------ // Get attributes // ------------------------------------------------------------------ const XMLCh* const processContents = getElementAttValue(elem, SchemaSymbols::fgATT_PROCESSCONTENTS); const XMLCh* const nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE); // ------------------------------------------------------------------ // Set default node type based on 'processContents' value // ------------------------------------------------------------------ ContentSpecNode::NodeTypes anyType = ContentSpecNode::Any; ContentSpecNode::NodeTypes anyLocalType = ContentSpecNode::Any_NS; ContentSpecNode::NodeTypes anyOtherType = ContentSpecNode::Any_Other; if ((processContents && *processContents) && !XMLString::equals(processContents, SchemaSymbols::fgATTVAL_STRICT)) { if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_LAX)) { anyType = ContentSpecNode::Any_Lax; anyOtherType = ContentSpecNode::Any_Other_Lax; anyLocalType = ContentSpecNode::Any_NS_Lax; } else if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_SKIP)) { anyType = ContentSpecNode::Any_Skip; anyOtherType = ContentSpecNode::Any_Other_Skip; anyLocalType = ContentSpecNode::Any_NS_Skip; } } // ------------------------------------------------------------------ // Process 'namespace' attribute // ------------------------------------------------------------------ ContentSpecNode* retSpecNode = 0; if ((!nameSpace || !*nameSpace) || XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDANY)) { retSpecNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( new (fGrammarPoolMemoryManager) QName ( XMLUni::fgZeroLenString , XMLUni::fgZeroLenString , fEmptyNamespaceURI , fGrammarPoolMemoryManager ) , false , fGrammarPoolMemoryManager ); retSpecNode->setType(anyType); } else if (XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER)) { retSpecNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( new (fGrammarPoolMemoryManager) QName ( XMLUni::fgZeroLenString , XMLUni::fgZeroLenString , fTargetNSURI, fGrammarPoolMemoryManager ) , false , fGrammarPoolMemoryManager ); retSpecNode->setType(anyOtherType); } else { XMLStringTokenizer nameSpaceTokens(nameSpace, fMemoryManager); ValueVectorOf uriList(8, fGrammarPoolMemoryManager); Janitor firstNode(0); Janitor secondNode(0); DatatypeValidator* anyURIDV = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYURI); while (nameSpaceTokens.hasMoreTokens()) { const XMLCh* tokenElem = nameSpaceTokens.nextToken(); int uriIndex = fEmptyNamespaceURI; if (!XMLString::equals(tokenElem,SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL)) { // not ##local if (XMLString::equals(tokenElem,SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE)) { uriIndex = fTargetNSURI; } else { try { anyURIDV->validate(tokenElem , fSchemaInfo->getValidationContext() , fMemoryManager); } catch(const XMLException& excep) { reportSchemaError(elem, excep); } uriIndex = fURIStringPool->addOrFind(tokenElem); } } if (uriList.containsElement(uriIndex)) { continue; } uriList.addElement(uriIndex); firstNode.release(); firstNode.reset( new (fGrammarPoolMemoryManager) ContentSpecNode ( new (fGrammarPoolMemoryManager) QName ( XMLUni::fgZeroLenString , XMLUni::fgZeroLenString , uriIndex, fGrammarPoolMemoryManager ) , false , fGrammarPoolMemoryManager )); firstNode.get()->setType(anyLocalType); if (secondNode.get() == 0) { secondNode.reset(firstNode.release()); } else { ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( ContentSpecNode::Any_NS_Choice , secondNode.get() , firstNode.get() , true , true , fGrammarPoolMemoryManager ); secondNode.release(); secondNode.reset(newNode); firstNode.release(); } } firstNode.release(); retSpecNode = secondNode.release(); } // Store annotation if (retSpecNode && !janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(retSpecNode, janAnnot.release()); return retSpecNode; } /** * Traverse all * * * Content: (annotation?, element*) * */ ContentSpecNode* TraverseSchema::traverseAll(const DOMElement* const elem, bool& hasChildren) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); hasChildren = false; // ----------------------------------------------------------------------- // Check attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_All, this, false, fNonXSAttList ); // ----------------------------------------------------------------------- // Process contents // ----------------------------------------------------------------------- DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } Janitor janAnnot(fAnnotation); if (child == 0) { return 0; } Janitor left(0); Janitor right(0); Janitor contentSpecNode(0); bool hadContent = false; for (; child != 0; child = XUtil::getNextSiblingElement(child)) { hasChildren = true; contentSpecNode.release(); const XMLCh* childName = child->getLocalName(); if (XMLString::equals(childName, SchemaSymbols::fgELT_ELEMENT)) { SchemaElementDecl* elemDecl = traverseElementDecl(child); if (!elemDecl) continue; contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode ( elemDecl , fGrammarPoolMemoryManager )); checkMinMax(contentSpecNode.get(), child, All_Element); } else { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AllContentError, childName); continue; } hadContent = true; if (!left.get()) { left.reset(contentSpecNode.release()); } else if (!right.get()) { right.reset(contentSpecNode.release()); } else { ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( ContentSpecNode::All , left.get() , right.get() , true , true , fGrammarPoolMemoryManager ); left.release(); left.reset(newNode); right.release(); right.reset(contentSpecNode.release()); } } contentSpecNode.release(); if (hadContent) { ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( ContentSpecNode::All , left.get() , right.get() , true , true , fGrammarPoolMemoryManager ); left.release(); left.reset(newNode); if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(left.get(), janAnnot.release()); } right.release(); return left.release(); } /** * Traverses Schema attribute declaration. * * * Content: (annotation? , simpleType?) * * * @param elem: the declaration of the attribute under consideration * * @param typeInfo: Contains the complex type info of the element to which * the attribute declaration is attached. * */ void TraverseSchema::traverseAttributeDecl(const DOMElement* const elem, ComplexTypeInfo* const typeInfo, const bool topLevel) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); bool nameEmpty = (!name || !*name); bool refEmpty = (!ref || !*ref); if (nameEmpty && refEmpty) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttribute); return; } if (topLevel && nameEmpty) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameAttribute); return; } // ------------------------------------------------------------------ // Check attributes // ------------------------------------------------------------------ unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_AttributeGlobal : (refEmpty) ? GeneralAttributeCheck::E_AttributeLocal : GeneralAttributeCheck::E_AttributeRef; fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList); const XMLCh* defaultVal = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT); const XMLCh* fixedVal = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED); const XMLCh* useVal = getElementAttValue(elem, SchemaSymbols::fgATT_USE); const XMLCh* attForm = getElementAttValue(elem, SchemaSymbols::fgATT_FORM); const XMLCh* dvType = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE, DatatypeValidator::QName); DOMElement* simpleType = checkContent(elem, XUtil::getFirstChildElement(elem), true); Janitor janAnnot(fAnnotation); bool badContent = false; while (simpleType != 0) { const XMLCh* contentName = simpleType->getLocalName(); if (XMLString::equals(SchemaSymbols::fgELT_SIMPLETYPE, contentName)) { if (XUtil::getNextSiblingElement(simpleType) != 0) { badContent = true; } break; } badContent = true; simpleType = XUtil::getNextSiblingElement(simpleType); } if (badContent) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttributeContent, (name) ? name : ref); } if (defaultVal) { if (fixedVal) { fixedVal = 0; reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeDefaultFixedValue, (name) ? name : ref); } if ((useVal && *useVal) && !XMLString::equals(useVal, SchemaSymbols::fgATTVAL_OPTIONAL)) { useVal = 0; reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotOptionalDefaultAttValue, (name) ? name : ref); } } // processing ref if (!refEmpty && !topLevel) { // Check ref representation OK - 3.2.3::3.2 if (attForm || dvType || (simpleType != 0)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeRefContentError, (name) ? name : ref); } processAttributeDeclRef(elem, typeInfo, ref, useVal, defaultVal, fixedVal); return; } if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); janAnnot.reset(fAnnotation); } // processing 'name' if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) || XMLString::equals(name, XMLUni::fgXMLNSString)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ATTRIBUTE, name); return; } // Check for duplicate declaration const XMLCh* qualified = SchemaSymbols::fgATTVAL_QUALIFIED; int uriIndex = fEmptyNamespaceURI; if ((fTargetNSURIString && *fTargetNSURIString) && (topLevel || XMLString::equals(attForm, qualified) || ((fSchemaInfo->getElemAttrDefaultQualified() & Attr_Def_Qualified) && (!attForm || !*attForm)))) { uriIndex = fTargetNSURI; } // make sure that attribute namespace is not xsi uri if (XMLString::equals(fTargetNSURIString, SchemaSymbols::fgURI_XSI)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttTNS, name); return; } if (typeInfo && typeInfo->getAttDef(name, uriIndex) != 0) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name); return; } else if (fCurrentAttGroupInfo && fCurrentAttGroupInfo->containsAttribute(name, uriIndex)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name); return; } DatatypeValidator* dv = 0; XMLAttDef::AttTypes attType = XMLAttDef::Simple; SchemaInfo* saveInfo = fSchemaInfo; if (simpleType != 0) { if (dvType && *dvType) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeWithTypeAndSimpleType, name); } dv = traverseSimpleTypeDecl(simpleType, false); } else if (!dvType || !*dvType) { dv = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYSIMPLETYPE); } else { checkEnumerationRequiredNotation(elem, name, dvType); const XMLCh* localPart = getLocalPart(dvType); const XMLCh* prefix = getPrefix(dvType); const XMLCh* typeURI = resolvePrefixToURI(elem, prefix); DatatypeValidator* dvBack = 0; if (XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { dv = fDatatypeRegistry->getDatatypeValidator(localPart); dvBack = dv; } else { //isn't of the schema for schemas namespace... dv = getAttrDatatypeValidatorNS(elem, localPart, typeURI); dvBack = dv; while(dv != 0 && !XMLString::equals(dv->getTypeUri(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { dv = dv->getBaseValidator(); } if(dv) localPart = dv->getTypeLocalName(); } if(dv) { if (XMLString::equals(localPart,XMLUni::fgIDString)) { attType = XMLAttDef::ID; } else if (XMLString::equals(localPart,XMLUni::fgIDRefString)) { attType = XMLAttDef::IDRef; } else if (XMLString::equals(localPart,XMLUni::fgIDRefsString)) { attType = XMLAttDef::IDRefs; } else if (XMLString::equals(localPart,XMLUni::fgEntityString)) { attType = XMLAttDef::Entity; } else if (XMLString::equals(localPart,XMLUni::fgEntitiesString)) { attType = XMLAttDef::Entities; } else if (XMLString::equals(localPart,XMLUni::fgNmTokenString)) { attType = XMLAttDef::NmToken; } else if (XMLString::equals(localPart,XMLUni::fgNmTokensString)) { attType = XMLAttDef::NmTokens; } else if (XMLString::equals(localPart,XMLUni::fgNotationString)) { attType = XMLAttDef::Notation; } else { attType = XMLAttDef::Simple; } } else attType = XMLAttDef::Simple; dv = dvBack; if (!dv) { reportSchemaError ( elem , XMLUni::fgXMLErrDomain , XMLErrs::AttributeSimpleTypeNotFound , typeURI , localPart , name ); } } // restore schema information, if necessary fSchemaInfo = saveInfo; bool required = false; bool prohibited = false; if (useVal && *useVal) { if (XMLString::equals(useVal, SchemaSymbols::fgATTVAL_REQUIRED)) { required = true; } else if (XMLString::equals(useVal, SchemaSymbols::fgATTVAL_PROHIBITED)) { prohibited = true; } } // validate fixed/default values const XMLCh* valueToCheck = defaultVal ? defaultVal : fixedVal; bool ofTypeID = (dv && dv->getType() == DatatypeValidator::ID); if (attType == XMLAttDef::Simple && dv && valueToCheck) { short wsFacet = dv->getWSFacet(); if((wsFacet == DatatypeValidator::REPLACE && !XMLString::isWSReplaced(valueToCheck)) || (wsFacet == DatatypeValidator::COLLAPSE && !XMLString::isWSCollapsed(valueToCheck))) { XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager); ArrayJanitor tempURIName(normalizedValue, fMemoryManager); if(wsFacet == DatatypeValidator::REPLACE) XMLString::replaceWS(normalizedValue, fMemoryManager); else if(wsFacet == DatatypeValidator::COLLAPSE) XMLString::collapseWS(normalizedValue, fMemoryManager); valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue)); } try { dv->validate(valueToCheck , fSchemaInfo->getValidationContext() , fMemoryManager); } catch (const XMLException& excep) { reportSchemaError(elem, excep); } catch(const OutOfMemoryException&) { throw; } catch(...) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueToCheck); } } else if((attType == XMLAttDef::NmTokens || attType==XMLAttDef::IDRefs || attType==XMLAttDef::Entities) && valueToCheck && !XMLString::isWSCollapsed(valueToCheck)) { XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager); ArrayJanitor tempURIName(normalizedValue, fMemoryManager); XMLString::collapseWS(normalizedValue, fMemoryManager); valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue)); } if (ofTypeID && valueToCheck) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3, name); } // check for multiple attributes with type derived from ID if (!topLevel && ofTypeID) { if (fCurrentAttGroupInfo) { if (fCurrentAttGroupInfo->containsTypeWithId()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, name); return; } fCurrentAttGroupInfo->setTypeWithId(true); } else { if (typeInfo->containsAttWithTypeId()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, name); return; } typeInfo->setAttWithTypeId(true); } } // create SchemaAttDef SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef ( XMLUni::fgZeroLenString , name , uriIndex , attType , XMLAttDef::Implied , fGrammarPoolMemoryManager ); attDef->setDatatypeValidator(dv); if (prohibited) { attDef->setDefaultType(XMLAttDef::Prohibited); } else if (required) { if (fixedVal) { attDef->setDefaultType(XMLAttDef::Required_And_Fixed); } else { attDef->setDefaultType(XMLAttDef::Required); } } else { if (fixedVal) { attDef->setDefaultType(XMLAttDef::Fixed); } else if (defaultVal) { attDef->setDefaultType(XMLAttDef::Default); } } if (valueToCheck) { attDef->setValue(valueToCheck); } if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(attDef, janAnnot.release()); if (topLevel) { fAttributeDeclRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), attDef); attDef->setPSVIScope(PSVIDefs::SCP_GLOBAL); } else { if (typeInfo) { typeInfo->addAttDef(attDef); if (!fCurrentAttGroupInfo) attDef->setPSVIScope(PSVIDefs::SCP_LOCAL); } if (fCurrentAttGroupInfo) { fCurrentAttGroupInfo->addAttDef(attDef, (typeInfo != 0)); } } } /** * Traverses Schema element declaration. * * * * @param elem: the declaration of the element under consideration */ SchemaElementDecl* TraverseSchema::traverseElementDecl(const DOMElement* const elem, const bool topLevel) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // if local element and ref attribute exists if (!topLevel) { const XMLCh* refName = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); if (refName) return processElementDeclRef(elem, refName); } // check for empty name const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); if (!name || !*name) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefElement); return 0; } // make sure that name is a valid NCName if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ELEMENT, name); return 0; } // if element already exists, just return --- revisit, it should not happen if (topLevel) { SchemaElementDecl* retDecl = (SchemaElementDecl*) fSchemaGrammar->getElemDecl(fTargetNSURI, name, 0, Grammar::TOP_LEVEL_SCOPE); if (retDecl) return retDecl; } // Check attributes unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_ElementGlobal : GeneralAttributeCheck::E_ElementLocal; fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList); // check annotation const DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); // Put annotations on all elements for the situation where there is a group of // elements and not all have annotations. //if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) if (!fAnnotation && fScanner->getGenerateSyntheticAnnotations()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } Janitor janAnnot(fAnnotation); // Create element decl bool isDuplicate = false; const XMLCh* valueConstraint = 0; SchemaElementDecl* elemDecl = createSchemaElementDecl(elem, name, isDuplicate, valueConstraint, topLevel); if (!isDuplicate) { fSchemaGrammar->putElemDecl(elemDecl); if (valueConstraint) elemDecl->setDefaultValue(valueConstraint); if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(elemDecl, janAnnot.release()); if (fCurrentComplexType && elemDecl->getEnclosingScope() == fCurrentComplexType->getScopeDefined()) { fCurrentComplexType->addElement(elemDecl); elemDecl->setPSVIScope(PSVIDefs::SCP_LOCAL); } if (fCurrentGroupInfo && elemDecl->getEnclosingScope() == fCurrentGroupInfo->getScope()) { fCurrentGroupInfo->addElement(elemDecl); elemDecl->setPSVIScope(PSVIDefs::SCP_ABSENT); } } else { if (fAnnotation) { XSAnnotation* xsAnnot = fSchemaGrammar->getAnnotation(elemDecl); if (!xsAnnot) { fSchemaGrammar->putAnnotation(elemDecl, janAnnot.release()); } else { xsAnnot->setNext(janAnnot.release()); } } } // Process children bool anonymousType = false; ComplexTypeInfo* typeInfo = 0; DatatypeValidator* validator = 0; if (content != 0) { const XMLCh* contentName = content->getLocalName(); if (XMLString::equals(contentName, SchemaSymbols::fgELT_COMPLEXTYPE)) { const XMLCh* temp = content->getAttribute(SchemaSymbols::fgATT_NAME); if (temp && *temp) { // REVISIT - we are bypassing the complex type declaration. reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AnonComplexTypeWithName, name); } else { typeInfo = checkForComplexTypeInfo(content); if (typeInfo) { validator = typeInfo->getDatatypeValidator(); if (!isDuplicate) { //Recursing element if (typeInfo->getPreprocessed()) { const XMLCh* typeInfoName = typeInfo->getTypeName(); fSchemaInfo->addRecursingType(content, typeInfoName + XMLString::indexOf(typeInfoName, chComma) + 1); } } } } anonymousType = true; content = XUtil::getNextSiblingElement(content); } else if (XMLString::equals(contentName, SchemaSymbols::fgELT_SIMPLETYPE)) { const XMLCh* temp = content->getAttribute(SchemaSymbols::fgATT_NAME); if (temp && *temp) // REVISIT - we are bypassing the simple type declaration. reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AnonSimpleTypeWithName, name); else validator = checkForSimpleTypeValidator(content); anonymousType = true; content = XUtil::getNextSiblingElement(content); } // Check for identity constraints if (content != 0) { content = checkIdentityConstraintContent(content); if (content != 0) reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::InvalidElementContent); } } // Handle 'type' attribute const XMLCh* typeStr = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE, DatatypeValidator::QName); if (typeStr) { if (anonymousType) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::ElementWithTypeAndAnonType, name); } else if (*typeStr) { const XMLCh* typeLocalPart = getLocalPart(typeStr); const XMLCh* typePrefix = getPrefix(typeStr); const XMLCh* typeURI = resolvePrefixToURI(elem, typePrefix); if (!XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) || !XMLString::equals(typeLocalPart, SchemaSymbols::fgATTVAL_ANYTYPE)) { checkEnumerationRequiredNotation(elem, name, typeStr); bool noErrorFound = true; const XMLCh* anotherSchemaURI = checkTypeFromAnotherSchema(elem, typeStr); // get complex type info typeInfo = getElementComplexTypeInfo(elem, typeStr, anotherSchemaURI); // get simple type validtor - if not a complex type if (typeInfo) validator = typeInfo->getDatatypeValidator(); else validator = getElementTypeValidator(elem, typeStr, noErrorFound, anotherSchemaURI); } } } // check for duplicate elements with different types. if (isDuplicate) { DatatypeValidator* eltDV = elemDecl->getDatatypeValidator(); ComplexTypeInfo* eltTypeInfo = elemDecl->getComplexTypeInfo(); if ( (eltTypeInfo != typeInfo) || (eltDV != validator)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, name); } } // Set element declararion type information else { elemDecl->setDatatypeValidator(validator); elemDecl->setComplexTypeInfo(typeInfo); if (validator) elemDecl->setModelType(SchemaElementDecl::Simple); else if (typeInfo) elemDecl->setModelType((SchemaElementDecl::ModelTypes)typeInfo->getContentType()); if (topLevel) { // Handle the substitutionGroup const XMLCh* subsGroupName = getElementAttValue(elem, SchemaSymbols::fgATT_SUBSTITUTIONGROUP, DatatypeValidator::QName); if (subsGroupName && *subsGroupName) processSubstitutionGroup(elem, elemDecl, typeInfo, validator, subsGroupName); } // process identity constraints DOMElement* ic = XUtil::getFirstChildElementNS( elem, fgIdentityConstraints, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, 3); if (ic) processElemDeclIC(ic, elemDecl); } if (!typeInfo && !validator) { if (!isDuplicate) { elemDecl->setModelType(SchemaElementDecl::Any); elemDecl->setAttWildCard( new (fGrammarPoolMemoryManager) SchemaAttDef( XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, fEmptyNamespaceURI, XMLAttDef::Any_Any, XMLAttDef::ProcessContents_Lax, fGrammarPoolMemoryManager ) ); } } else if (valueConstraint) { if (!checkElemDeclValueConstraint(elem, elemDecl, valueConstraint, typeInfo, validator) && !isDuplicate) { int miscFlags = elemDecl->getMiscFlags(); miscFlags &= ~ SchemaSymbols::XSD_FIXED; elemDecl->setDefaultValue(0); elemDecl->setMiscFlags(miscFlags); } } return elemDecl; } /** * Traverses Schema notation declaration. * * * Content: (annotation?) * * * @param elem: the declaration of the element under consideration */ const XMLCh* TraverseSchema::traverseNotationDecl(const DOMElement* const elem) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_Notation, this, true, fNonXSAttList ); // ----------------------------------------------------------------------- // Process notation attributes/elements // ----------------------------------------------------------------------- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); bool nameEmpty = (!name || !*name) ? true : false; if (nameEmpty) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement, SchemaSymbols::fgELT_NOTATION); return 0; } if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_NOTATION, name); return 0; } if (fNotationRegistry->containsKey(name, fTargetNSURI)) { return name; } if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); const XMLCh* publicId = getElementAttValue(elem, SchemaSymbols::fgATT_PUBLIC); const XMLCh* systemId = getElementAttValue(elem, SchemaSymbols::fgATT_SYSTEM, DatatypeValidator::AnyURI); fNotationRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), fTargetNSURI, 0); // for PSVI we need to store the notational decl XMLNotationDecl* decl = new (fGrammarPoolMemoryManager) XMLNotationDecl ( name, publicId, systemId, 0, fGrammarPoolMemoryManager ); decl->setNameSpaceId(fTargetNSURI); fSchemaGrammar->putNotationDecl(decl); if (fAnnotation) fSchemaGrammar->putAnnotation(decl, fAnnotation); else if (fScanner->getGenerateSyntheticAnnotations() && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); fSchemaGrammar->putAnnotation(decl, fAnnotation); } return name; } const XMLCh* TraverseSchema::traverseNotationDecl(const DOMElement* const elem, const XMLCh* const name, const XMLCh* const uriStr) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); unsigned int uriId = fURIStringPool->addOrFind(uriStr); SchemaInfo* saveInfo = fSchemaInfo; if (fTargetNSURI != (int) uriId) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(uriStr); if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); return 0; } Grammar* grammar = fGrammarResolver->getGrammar(uriStr); if (grammar == 0 || grammar->getGrammarType() != Grammar::SchemaGrammarType) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); return 0; } SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uriStr, name); return 0; } fSchemaInfo = impInfo; fTargetNSURI = fSchemaInfo->getTargetNSURI(); } DOMElement* notationElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Notation, SchemaSymbols::fgELT_NOTATION, name, &fSchemaInfo); if (notationElem == 0) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Notation_DeclNotFound, uriStr, name); return 0; } const XMLCh* notationName = traverseNotationDecl(notationElem); fSchemaInfo = saveInfo; fTargetNSURI = fSchemaInfo->getTargetNSURI(); return notationName; } /** * Traverses Schema list simple type declaration. * * * Content: (annotation?, simpleType?) * * */ DatatypeValidator* TraverseSchema::traverseByList(const DOMElement* const rootElem, const DOMElement* const contentElem, const XMLCh* const typeName, const XMLCh* const qualifiedName, const int finalSet, Janitor* const janAnnot) { NamespaceScopeManager nsMgr(contentElem, fSchemaInfo, this); DatatypeValidator* baseValidator = 0; const XMLCh* baseTypeName = getElementAttValue(contentElem, SchemaSymbols::fgATT_ITEMTYPE, DatatypeValidator::QName); fAttributeCheck.checkAttributes( contentElem, GeneralAttributeCheck::E_List, this, false, fNonXSAttList ); const DOMElement* tempEl = XUtil::getNextSiblingElement(contentElem); if (tempEl != 0) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError, tempEl->getLocalName()); } DOMElement* content = 0; if (!baseTypeName || !*baseTypeName) { // must 'see' content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), false); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } if (!content) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInList, typeName); popCurrentTypeNameStack(); return 0; } if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { baseValidator = checkForSimpleTypeValidator(content, SchemaSymbols::XSD_LIST); } else { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName); popCurrentTypeNameStack(); return 0; } content = XUtil::getNextSiblingElement(content); } else { // base was provided - get proper validator baseValidator = findDTValidator(contentElem, typeName, baseTypeName, SchemaSymbols::XSD_LIST); content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), true); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } } DatatypeValidator* newDV = 0; if (baseValidator) { if (!baseValidator->isAtomic()) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::AtomicItemType, baseTypeName); } else { // 'content' should be empty // If an annotation was encountered we have already traversed it in // checkContent in the case of a base provided (only allowed child is // an annotation). if (content != 0) { // report an error and continue reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeDerivationByListError, typeName); } // create & register validator for "generated" type try { newDV = fDatatypeRegistry->createDatatypeValidator( qualifiedName, baseValidator, 0, 0, true, finalSet, true, fGrammarPoolMemoryManager); } catch (const XMLException& excep) { reportSchemaError(contentElem, excep); } catch(const OutOfMemoryException&) { throw; } catch(...) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::DatatypeValidatorCreationError, typeName); } } } popCurrentTypeNameStack(); return newDV; } /** * Traverses Schema restriction simple type declaration. * * * Content: (annotation?, (simpleType?, * (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)) * * */ DatatypeValidator* TraverseSchema::traverseByRestriction(const DOMElement* const rootElem, const DOMElement* const contentElem, const XMLCh* const typeName, const XMLCh* const qualifiedName, const int finalSet, Janitor* const janAnnot) { NamespaceScopeManager nsMgr(contentElem, fSchemaInfo, this); DatatypeValidator* baseValidator = 0; DatatypeValidator* newDV = 0; const XMLCh* baseTypeName = getElementAttValue(contentElem, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); fAttributeCheck.checkAttributes( contentElem, GeneralAttributeCheck::E_Restriction, this, false, fNonXSAttList ); const DOMElement* tempEl = XUtil::getNextSiblingElement(contentElem); if (tempEl != 0) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError, tempEl->getLocalName()); } DOMElement* content = 0; if (!baseTypeName || !*baseTypeName) { // must 'see' content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), false); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } if (content == 0) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInRestriction); popCurrentTypeNameStack(); return 0; } if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { baseValidator = checkForSimpleTypeValidator(content); } else { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName); popCurrentTypeNameStack(); return 0; } // Check for facets content = XUtil::getNextSiblingElement(content); } else { // base was provided - get proper validator baseValidator = findDTValidator(contentElem, typeName, baseTypeName, SchemaSymbols::XSD_RESTRICTION); content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), true); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } } if (baseValidator) { // Get facets if any existing typedef RefHashTableOf KVRefHash; Janitor janFacets(0); //RefHashTableOf* facets = 0; typedef RefArrayVectorOf XMLChRefArray; Janitor enums(0); //RefArrayVectorOf* enums = 0; XMLBuffer pattern(128, fGrammarPoolMemoryManager); Janitor janEnumAnnot(0); Janitor janPatternAnnot(0); XMLCh fixedFlagStr[16]; unsigned int fixedFlag = 0; unsigned short scope = 0; bool isFirstPattern = true; bool sawPattern = false; while (content != 0) { if (content->getNodeType() == DOMNode::ELEMENT_NODE) { NamespaceScopeManager nsMgr(content, fSchemaInfo, this); const XMLCh* facetName = content->getLocalName(); bool bContinue=false; // workaround for Borland bug with 'continue' in 'catch' try { scope = fAttributeCheck.getFacetId(facetName, fMemoryManager); } catch(const OutOfMemoryException&) { throw; } catch (...) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::InvalidFacetName, facetName); content = XUtil::getNextSiblingElement(content); bContinue=true; } if(bContinue) continue; fAttributeCheck.checkAttributes( content, scope, this, false, fNonXSAttList ); if (checkContent(rootElem, XUtil::getFirstChildElement(content), true) != 0) reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); const XMLCh* attValue = content->getAttribute(SchemaSymbols::fgATT_VALUE); if (janFacets.get() == 0) { janFacets.reset(new (fGrammarPoolMemoryManager) RefHashTableOf(29, true, fGrammarPoolMemoryManager)); } if (XMLString::equals(facetName, SchemaSymbols::fgELT_ENUMERATION)) { if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(content, fNonXSAttList); } if (fAnnotation) { if (janEnumAnnot.isDataNull()) janEnumAnnot.reset(fAnnotation); else janEnumAnnot.get()->setNext(fAnnotation); } // REVISIT // if validator is a notation datatype validator, we need // to get the qualified name first before adding it to the // enum buffer if (!enums.get()) { enums.reset(new (fGrammarPoolMemoryManager) RefArrayVectorOf(8, true, fGrammarPoolMemoryManager)); } if (baseValidator->getType() == DatatypeValidator::NOTATION) { const XMLCh* localPart = getLocalPart(attValue); const XMLCh* prefix = getPrefix(attValue); const XMLCh* uriStr = (prefix && *prefix) ? resolvePrefixToURI(content, prefix) : fTargetNSURIString; unsigned int uriId = fURIStringPool->addOrFind(uriStr); if (!fNotationRegistry->containsKey(localPart, uriId)) { traverseNotationDecl(content, localPart, uriStr); } if (uriStr && *uriStr) { fBuffer.set(uriStr); fBuffer.append(chColon); fBuffer.append(localPart); enums.get()->addElement(XMLString::replicate(fBuffer.getRawBuffer(), fGrammarPoolMemoryManager)); } else { enums.get()->addElement(XMLString::replicate(localPart, fGrammarPoolMemoryManager)); } } else if (baseValidator->getType() == DatatypeValidator::QName) { // We need the URI string for the prefix to determine // if that matches the value in the instance document. // Code was just comparing the string of prefix:localname // and if the schema and instance document had different // prefixes with the same URI string then we were giving an error. const XMLCh* prefix = getPrefix(attValue); const XMLCh* uriStr = (prefix && *prefix) ? resolvePrefixToURI(content, prefix) : fTargetNSURIString; enums.get()->addElement(XMLString::replicate(attValue, fGrammarPoolMemoryManager)); enums.get()->addElement(XMLString::replicate(uriStr, fGrammarPoolMemoryManager)); } else { enums.get()->addElement(XMLString::replicate(attValue, fGrammarPoolMemoryManager)); } } else if (XMLString::equals(facetName, SchemaSymbols::fgELT_PATTERN)) { if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(content, fNonXSAttList); } if (fAnnotation) { if (janPatternAnnot.isDataNull()) janPatternAnnot.reset(fAnnotation); else janPatternAnnot.get()->setNext(fAnnotation); } sawPattern = true; if (isFirstPattern) { // fBuffer.isEmpty() - overhead call isFirstPattern = false; pattern.set(attValue); } else { //datatypes: 5.2.4 pattern pattern.append(chPipe); pattern.append(attValue); } } else { if (janFacets.get()->containsKey(facetName)) { if (fAnnotation) delete fAnnotation; reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetName); } else { if (XMLString::equals(facetName, SchemaSymbols::fgELT_WHITESPACE) && baseValidator->getType() != DatatypeValidator::String && !XMLString::equals(attValue, SchemaSymbols::fgWS_COLLAPSE)) { if (fAnnotation) delete fAnnotation; reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::WS_CollapseExpected, attValue); } else { const XMLCh* facetStr = fStringPool->getValueForId(fStringPool->addOrFind(facetName)); KVStringPair* kv = new (fGrammarPoolMemoryManager) KVStringPair(facetStr, attValue, fGrammarPoolMemoryManager); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(content, fNonXSAttList); } if (fAnnotation) fSchemaGrammar->putAnnotation(kv, fAnnotation); janFacets.get()->put((void*) facetStr, kv); checkFixedFacet(content, facetStr, baseValidator, fixedFlag); } } } } content = XUtil::getNextSiblingElement(content); } // end while if (sawPattern) { KVStringPair* kv = new (fGrammarPoolMemoryManager) KVStringPair(SchemaSymbols::fgELT_PATTERN, pattern.getRawBuffer(), pattern.getLen(), fGrammarPoolMemoryManager); if (!janPatternAnnot.isDataNull()) fSchemaGrammar->putAnnotation(kv, janPatternAnnot.release()); janFacets.get()->put((void*) SchemaSymbols::fgELT_PATTERN, kv); } if (fixedFlag) { XMLString::binToText(fixedFlag, fixedFlagStr, 15, 10, fGrammarPoolMemoryManager); janFacets.get()->put((void*) SchemaSymbols::fgATT_FIXED, new (fGrammarPoolMemoryManager) KVStringPair(SchemaSymbols::fgATT_FIXED, fixedFlagStr, fGrammarPoolMemoryManager)); } if (enums.get() && !janEnumAnnot.isDataNull()) fSchemaGrammar->putAnnotation(enums.get(), janEnumAnnot.release()); try { newDV = fDatatypeRegistry->createDatatypeValidator(qualifiedName, baseValidator, janFacets.release(), enums.release(), false, finalSet, true, fGrammarPoolMemoryManager); } catch (const XMLException& excep) { reportSchemaError(contentElem, excep); } catch(const OutOfMemoryException&) { throw; } catch(...) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::DatatypeValidatorCreationError, typeName); } } popCurrentTypeNameStack(); return newDV; } /** * Traverses Schema union simple type declaration. * * * Content: (annotation?, simpleType*) * * */ DatatypeValidator* TraverseSchema::traverseByUnion(const DOMElement* const rootElem, const DOMElement* const contentElem, const XMLCh* const typeName, const XMLCh* const qualifiedName, const int finalSet, int baseRefContext, Janitor* const janAnnot) { NamespaceScopeManager nsMgr(contentElem, fSchemaInfo, this); fAttributeCheck.checkAttributes( contentElem, GeneralAttributeCheck::E_Union, this, false, fNonXSAttList ); const DOMElement* tempEl = XUtil::getNextSiblingElement(contentElem); if (tempEl != 0) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError, tempEl->getLocalName()); } const XMLCh* baseTypeName = getElementAttValue(contentElem, SchemaSymbols::fgATT_MEMBERTYPES); DatatypeValidator* baseValidator = 0; RefVectorOf* validators = new (fGrammarPoolMemoryManager) RefVectorOf(4, false, fGrammarPoolMemoryManager); Janitor > janValidators(validators); DOMElement* content = 0; if (baseTypeName && *baseTypeName) { //base was provided - get proper validator. XMLStringTokenizer unionMembers(baseTypeName, fGrammarPoolMemoryManager); int tokCount = unionMembers.countTokens(); for (int i = 0; i < tokCount; i++) { const XMLCh* memberTypeName = unionMembers.nextToken(); baseValidator = findDTValidator(contentElem, typeName, memberTypeName, SchemaSymbols::XSD_UNION); if (baseValidator == 0) { popCurrentTypeNameStack(); return 0; } validators->addElement(baseValidator); } content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), true); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } } else { // must 'see' content = checkContent(rootElem, XUtil::getFirstChildElement(contentElem), false); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(contentElem, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } if (content == 0) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInUnion, typeName); popCurrentTypeNameStack(); return 0; } if (!XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName); popCurrentTypeNameStack(); return 0; } } // process union content of simpleType children if any while (content != 0) { if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { baseValidator = checkForSimpleTypeValidator(content, baseRefContext | SchemaSymbols::XSD_UNION); if (baseValidator == 0) { popCurrentTypeNameStack(); return 0; } validators->addElement(baseValidator); } else { // REVISIT - should we break. For now, we will continue and move to // the next sibling reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName); } content = XUtil::getNextSiblingElement(content); } // end while DatatypeValidator* newDV = 0; janValidators.orphan(); try { newDV = fDatatypeRegistry->createDatatypeValidator(qualifiedName, validators, finalSet, true, fGrammarPoolMemoryManager); } catch (const XMLException& excep) { reportSchemaError(contentElem, excep); } catch(const OutOfMemoryException&) { throw; } catch(...) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::DatatypeValidatorCreationError, typeName); } popCurrentTypeNameStack(); return newDV; } /** * Traverse SimpleContent Declaration * * * * Content: (annotation? , (restriction | extension)) * * * * * Content: (annotation?, (simpleType?, (minExclusive | minInclusive * | maxExclusive | maxInclusive | totalDigits | fractionDigits * | length | minLength | maxLength | enumeration | pattern * | whiteSpace)*)?, ((attribute | attributeGroup)* , anyAttribute?)) * * * * Content: (annotation? , ((attribute | attributeGroup)* , anyAttribute?)) * * */ void TraverseSchema::traverseSimpleContentDecl(const XMLCh* const typeName, const XMLCh* const qualifiedName, const DOMElement* const contentDecl, ComplexTypeInfo* const typeInfo, Janitor* const janAnnot) { NamespaceScopeManager nsMgr(contentDecl, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- bool preProcessFlag = typeInfo->getPreprocessed(); if (!preProcessFlag) { fAttributeCheck.checkAttributes( contentDecl, GeneralAttributeCheck::E_SimpleContent , this, false, fNonXSAttList ); } // ----------------------------------------------------------------------- // Set the content type to be simple, and initialize content spec handle // ----------------------------------------------------------------------- typeInfo->setContentType(SchemaElementDecl::Simple); // ----------------------------------------------------------------------- // Process annotation if any // ----------------------------------------------------------------------- DOMElement* simpleContent = checkContent(contentDecl, XUtil::getFirstChildElement(contentDecl), false, !preProcessFlag); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(contentDecl, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } // If there are no children, return if (simpleContent == 0) { reportSchemaError(contentDecl, XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent); throw TraverseSchema::InvalidComplexTypeInfo; } NamespaceScopeManager nsMgr2(simpleContent, fSchemaInfo, this); // ----------------------------------------------------------------------- // The content should be either "restriction" or "extension" // ----------------------------------------------------------------------- if (!preProcessFlag) { const XMLCh* const contentName = simpleContent->getLocalName(); if (XMLString::equals(contentName, SchemaSymbols::fgATTVAL_RESTRICTION)) { fAttributeCheck.checkAttributes( simpleContent, GeneralAttributeCheck::E_Restriction , this, false, fNonXSAttList ); typeInfo->setDerivedBy(SchemaSymbols::XSD_RESTRICTION); } else if (XMLString::equals(contentName, SchemaSymbols::fgATTVAL_EXTENSION)) { fAttributeCheck.checkAttributes( simpleContent, GeneralAttributeCheck::E_Extension , this, false, fNonXSAttList ); typeInfo->setDerivedBy(SchemaSymbols::XSD_EXTENSION); } else { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContent); throw TraverseSchema::InvalidComplexTypeInfo; } } //Skip over any annotations in the restriction or extension elements DOMElement* content = checkContent(simpleContent, XUtil::getFirstChildElement(simpleContent), true, !preProcessFlag); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(simpleContent, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } // ----------------------------------------------------------------------- // Handle the base type name // ----------------------------------------------------------------------- const XMLCh* baseName = getElementAttValue(simpleContent, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); if (!baseName || !*baseName) { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase); throw TraverseSchema::InvalidComplexTypeInfo; } const XMLCh* prefix = getPrefix(baseName); const XMLCh* localPart = getLocalPart(baseName); const XMLCh* uri = resolvePrefixToURI(simpleContent, prefix); // check for 'anyType' if (XMLString::equals(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) && XMLString::equals(localPart, SchemaSymbols::fgATTVAL_ANYTYPE)) { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName); throw TraverseSchema::InvalidComplexTypeInfo; } processBaseTypeInfo(simpleContent, baseName, localPart, uri, typeInfo); ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo(); DatatypeValidator* baseValidator = typeInfo->getBaseDatatypeValidator(); if (baseValidator != 0 && baseTypeInfo == 0) { // check that the simpleType does not preclude derivation by extension if ((baseValidator->getFinalSet() & SchemaSymbols::XSD_EXTENSION) == typeInfo->getDerivedBy()) { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::DisallowedSimpleTypeExtension, baseName, typeName); throw TraverseSchema::InvalidComplexTypeInfo; } //Schema Spec: 5.11: Complex Type Definition Properties Correct: 2 if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION) { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexTypeBase, baseName); throw TraverseSchema::InvalidComplexTypeInfo; } } // check that the base isn't a complex type with complex content // and that derivation method is not included in 'final' bool simpleTypeRequired = false; if (baseTypeInfo) { if (baseTypeInfo->getContentType() != SchemaElementDecl::Simple) { // Schema Errata: E1-27 if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION && ((baseTypeInfo->getContentType() == SchemaElementDecl::Mixed_Simple || baseTypeInfo->getContentType() == SchemaElementDecl::Mixed_Complex) && emptiableParticle(baseTypeInfo->getContentSpec()))) { simpleTypeRequired = true; } else { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName); throw TraverseSchema::InvalidComplexTypeInfo; } } if ((baseTypeInfo->getFinalSet() & typeInfo->getDerivedBy()) != 0) { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivation, baseName); throw TraverseSchema::InvalidComplexTypeInfo; } } // ----------------------------------------------------------------------- // Process the content of the derivation // ----------------------------------------------------------------------- if (typeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION) { if(baseTypeInfo) typeInfo->setBaseDatatypeValidator(baseTypeInfo->getDatatypeValidator()); if (content != 0) { // --------------------------------------------------------------- // There may be a simple type definition in the restriction // element. The data type validator will be based on it, if // specified // --------------------------------------------------------------- if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_SIMPLETYPE)) { DatatypeValidator* simpleTypeDV = traverseSimpleTypeDecl(content, false); if (simpleTypeDV) { // Check that the simpleType validator is validly derived // from base DatatypeValidator* baseDV = typeInfo->getBaseDatatypeValidator(); if (baseDV && !baseDV->isSubstitutableBy(simpleTypeDV)) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::InvalidContentRestriction); throw TraverseSchema::InvalidComplexTypeInfo; } typeInfo->setBaseDatatypeValidator(simpleTypeDV); content = XUtil::getNextSiblingElement(content); } else { throw TraverseSchema::InvalidComplexTypeInfo; } } // Schema Errata E1-27 // Complex Type Definition Restriction OK: 2.2 else if (simpleTypeRequired) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::CT_SimpleTypeChildRequired); throw TraverseSchema::InvalidComplexTypeInfo; } // --------------------------------------------------------------- // Build up the facet info // --------------------------------------------------------------- RefHashTableOf* facets = 0; RefArrayVectorOf* enums = 0; XMLBuffer pattern(128, fGrammarPoolMemoryManager); XMLCh fixedFlagStr[16]; unsigned int fixedFlag = 0; unsigned short scope = 0; bool isFirstPattern = true; while (content != 0) { const XMLCh* facetName = content->getLocalName(); bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch' // if not a valid facet, break from the loop try { scope = fAttributeCheck.getFacetId(facetName, fMemoryManager); } catch(const OutOfMemoryException&) { throw; } catch(...) { bDoBreak=true; } if(bDoBreak) break; if (content->getNodeType() == DOMNode::ELEMENT_NODE) { fAttributeCheck.checkAttributes(content, scope, this); const XMLCh* attValue = content->getAttribute(SchemaSymbols::fgATT_VALUE); if (facets == 0) { facets = new (fGrammarPoolMemoryManager) RefHashTableOf(29, true, fGrammarPoolMemoryManager); } if (XMLString::equals(facetName, SchemaSymbols::fgELT_ENUMERATION)) { if (!enums) { enums = new (fGrammarPoolMemoryManager) RefArrayVectorOf(8, true, fGrammarPoolMemoryManager); } enums->addElement(XMLString::replicate(attValue, fGrammarPoolMemoryManager)); } else if (XMLString::equals(facetName, SchemaSymbols::fgELT_PATTERN)) { if (isFirstPattern) { // fBuffer.isEmpty() - overhead call isFirstPattern = false; pattern.set(attValue); } else { //datatypes: 5.2.4 pattern pattern.append(chPipe); pattern.append(attValue); } } else { if (facets->containsKey(facetName)) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetName); } else { const XMLCh* facetNameStr = fStringPool->getValueForId(fStringPool->addOrFind(facetName)); facets->put((void*) facetNameStr, new (fGrammarPoolMemoryManager) KVStringPair(facetNameStr, attValue, fGrammarPoolMemoryManager)); checkFixedFacet(content, facetNameStr, typeInfo->getBaseDatatypeValidator(), fixedFlag); } } } content = XUtil::getNextSiblingElement(content); } if (facets) { if (!pattern.isEmpty()) { facets->put ( (void*) SchemaSymbols::fgELT_PATTERN, new (fGrammarPoolMemoryManager) KVStringPair ( SchemaSymbols::fgELT_PATTERN , pattern.getRawBuffer() , pattern.getLen() , fGrammarPoolMemoryManager ) ); } if (fixedFlag) { XMLString::binToText(fixedFlag, fixedFlagStr, 15, 10, fGrammarPoolMemoryManager); facets->put((void*) SchemaSymbols::fgATT_FIXED, new (fGrammarPoolMemoryManager) KVStringPair(SchemaSymbols::fgATT_FIXED, fixedFlagStr, fGrammarPoolMemoryManager)); } try { DatatypeValidator* simpleDV = fDatatypeRegistry->createDatatypeValidator ( qualifiedName, typeInfo->getBaseDatatypeValidator(), facets, enums, false, 0, true, fGrammarPoolMemoryManager ); simpleDV->setAnonymous(); typeInfo->setDatatypeValidator(simpleDV); } catch (const XMLException& excep) { reportSchemaError(simpleContent, excep); } catch(const OutOfMemoryException&) { throw; } catch(...) { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::DatatypeValidatorCreationError, typeName); } } else { typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator()); } } else { // Schema Errata E1-27 // Complex Type Definition Restriction OK: 2.2 if (simpleTypeRequired) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::CT_SimpleTypeChildRequired); throw TraverseSchema::InvalidComplexTypeInfo; } typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator()); } } // end RESTRICTION else { // EXTENSION ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo(); if (baseTypeInfo!= 0) { typeInfo->setBaseDatatypeValidator(baseTypeInfo->getDatatypeValidator()); } typeInfo->setDatatypeValidator(typeInfo->getBaseDatatypeValidator()); } // ----------------------------------------------------------------------- // Process attributes if any // ----------------------------------------------------------------------- processAttributes(simpleContent, content, typeInfo); if (XUtil::getNextSiblingElement(simpleContent) != 0) { reportSchemaError(simpleContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInSimpleContent); } } // End of function traverseSimpleContentDecl /** * Traverse complexContent Declaration * * * * Content: (annotation? , (restriction | extension)) * * * * * Content: (annotation? , (group | all | choice | sequence)?, * ((attribute | attributeGroup)* , anyAttribute?)) * * * * Content: (annotation? , (group | all | choice | sequence)?, * ((attribute | attributeGroup)* , anyAttribute?)) * */ void TraverseSchema::traverseComplexContentDecl(const XMLCh* const typeName, const DOMElement* const contentDecl, ComplexTypeInfo* const typeInfo, const bool isMixed, Janitor* const janAnnot) { NamespaceScopeManager nsMgr(contentDecl, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check attributes // ----------------------------------------------------------------------- bool preProcessFlag = typeInfo->getPreprocessed(); if (!preProcessFlag) { fAttributeCheck.checkAttributes( contentDecl, GeneralAttributeCheck::E_ComplexContent , this, false, fNonXSAttList ); } // ----------------------------------------------------------------------- // Determine whether the content is mixed, or element-only // Setting here overrides any setting on the complex type decl // ----------------------------------------------------------------------- const XMLCh* const mixed = getElementAttValue(contentDecl, SchemaSymbols::fgATT_MIXED, DatatypeValidator::Boolean); bool mixedContent = isMixed; if (mixed) { if (XMLString::equals(mixed, SchemaSymbols::fgATTVAL_TRUE) || XMLString::equals(mixed, fgValueOne)) { mixedContent = true; } else if (XMLString::equals(mixed, SchemaSymbols::fgATTVAL_FALSE) || XMLString::equals(mixed, fgValueZero)) { mixedContent = false; } } // ----------------------------------------------------------------------- // Since the type must have complex content, set the simple type validators // to null // ----------------------------------------------------------------------- typeInfo->setDatatypeValidator(0); typeInfo->setBaseDatatypeValidator(0); DOMElement* complexContent = checkContent(contentDecl,XUtil::getFirstChildElement(contentDecl),false, !preProcessFlag); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(contentDecl, fNonXSAttList); } if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } // If there are no children, return if (complexContent == 0) { throw TraverseSchema::InvalidComplexTypeInfo; } NamespaceScopeManager nsMgr2(complexContent, fSchemaInfo, this); // ----------------------------------------------------------------------- // The content should be either "restriction" or "extension" // ----------------------------------------------------------------------- const XMLCh* const complexContentName = complexContent->getLocalName(); if (XMLString::equals(complexContentName, SchemaSymbols::fgELT_RESTRICTION)) { typeInfo->setDerivedBy(SchemaSymbols::XSD_RESTRICTION); } else if (XMLString::equals(complexContentName, SchemaSymbols::fgELT_EXTENSION)) { typeInfo->setDerivedBy(SchemaSymbols::XSD_EXTENSION); } else { reportSchemaError(complexContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexContent); throw TraverseSchema::InvalidComplexTypeInfo; } // ----------------------------------------------------------------------- // Handle the base type name // ----------------------------------------------------------------------- const XMLCh* baseName = getElementAttValue(complexContent, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); if (!baseName || !*baseName) { reportSchemaError(complexContent, XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase); throw TraverseSchema::InvalidComplexTypeInfo; } const XMLCh* prefix = getPrefix(baseName); const XMLCh* localPart = getLocalPart(baseName); const XMLCh* uri = resolvePrefixToURI(complexContent, prefix); bool isBaseAnyType = false; // ------------------------------------------------------------- // check if the base is "anyType" // ------------------------------------------------------------- if (XMLString::equals(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) && XMLString::equals(localPart, SchemaSymbols::fgATTVAL_ANYTYPE)) { isBaseAnyType = true; } else { processBaseTypeInfo(complexContent, baseName, localPart, uri, typeInfo); //Check that the base is a complex type if (typeInfo->getBaseComplexTypeInfo() == 0) { reportSchemaError(complexContent, XMLUni::fgXMLErrDomain, XMLErrs::BaseNotComplexType); throw TraverseSchema::InvalidComplexTypeInfo; } } if (fCurrentGroupInfo) // defer processing until later throw TraverseSchema::RecursingElement; // ----------------------------------------------------------------------- // Process the content of the derivation // ----------------------------------------------------------------------- //Skip over any annotations in the restriction or extension elements DOMElement* content = checkContent(complexContent, XUtil::getFirstChildElement(complexContent), true); if (fAnnotation) { if (janAnnot->isDataNull()) janAnnot->reset(fAnnotation); else janAnnot->get()->setNext(fAnnotation); } processComplexContent(complexContent, typeName, content, typeInfo, localPart, mixedContent, isBaseAnyType); if (XUtil::getNextSiblingElement(complexContent) != 0) { reportSchemaError(complexContent, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexContent); } } /** * * processContents = (lax | skip | strict) : strict * Content: (annotation?) * */ SchemaAttDef* TraverseSchema::traverseAnyAttribute(const DOMElement* const elem) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_AnyAttribute, this, false, fNonXSAttList ); // ------------------------------------------------------------------ // First, handle any ANNOTATION declaration // ------------------------------------------------------------------ if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AnyAttributeContentError); } if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } Janitor janAnnot(fAnnotation); // ------------------------------------------------------------------ // Get attributes // ------------------------------------------------------------------ const XMLCh* const processContents = getElementAttValue(elem, SchemaSymbols::fgATT_PROCESSCONTENTS); const XMLCh* const nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE); // ------------------------------------------------------------------ // Set default att type based on 'processContents' value // ------------------------------------------------------------------ XMLAttDef::DefAttTypes attDefType = XMLAttDef::ProcessContents_Strict; if ((!processContents || !*processContents) || XMLString::equals(processContents, SchemaSymbols::fgATTVAL_STRICT)) { // Do nothing - defaulted already } else if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_SKIP)) { attDefType = XMLAttDef::ProcessContents_Skip; } else if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_LAX)) { attDefType = XMLAttDef::ProcessContents_Lax; } // ------------------------------------------------------------------ // Process 'namespace' attribute // ------------------------------------------------------------------ int uriIndex = fEmptyNamespaceURI; XMLAttDef::AttTypes attType = XMLAttDef::Any_Any; ValueVectorOf namespaceList(8, fGrammarPoolMemoryManager); if ((!nameSpace || !*nameSpace) || XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDANY)) { // Do nothing - defaulted already } else if (XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER)) { attType = XMLAttDef::Any_Other; uriIndex = fTargetNSURI; } else { XMLStringTokenizer tokenizer(nameSpace, fGrammarPoolMemoryManager); DatatypeValidator* anyURIDV = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYURI); attType = XMLAttDef::Any_List; while (tokenizer.hasMoreTokens()) { const XMLCh* token = tokenizer.nextToken(); if (XMLString::equals(token, SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL)) { uriIndex = fEmptyNamespaceURI; } else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE)) { uriIndex = fTargetNSURI; } else { try { anyURIDV->validate(token , fSchemaInfo->getValidationContext() , fMemoryManager); } catch(const XMLException& excep) { reportSchemaError(elem, excep); } uriIndex = fURIStringPool->addOrFind(token); } if (!namespaceList.containsElement(uriIndex)) { namespaceList.addElement(uriIndex); } } uriIndex = fEmptyNamespaceURI; } // ------------------------------------------------------------------ // Create wildcard attribute // ------------------------------------------------------------------ SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, uriIndex, attType, attDefType, fGrammarPoolMemoryManager); if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(attDef, janAnnot.release()); if (namespaceList.size()) { attDef->setNamespaceList(&namespaceList); } return attDef; } /** * */ void TraverseSchema::traverseKey(const DOMElement* const icElem, SchemaElementDecl* const elemDecl) { NamespaceScopeManager nsMgr(icElem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( icElem, GeneralAttributeCheck::E_Key, this, false, fNonXSAttList ); // ----------------------------------------------------------------------- // Create identity constraint // ----------------------------------------------------------------------- const XMLCh* name = getElementAttValue(icElem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_KEY, name); return; } if (!fIdentityConstraintNames) { fIdentityConstraintNames = new (fMemoryManager) RefHash2KeysTableOf(29, (bool) false, fMemoryManager); } else if (fIdentityConstraintNames->containsKey(name, fTargetNSURI)) { reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_DuplicateDecl, name); return; } IC_Key* icKey = new (fGrammarPoolMemoryManager) IC_Key(name, elemDecl->getBaseName(), fGrammarPoolMemoryManager); Janitor janKey(icKey); fIdentityConstraintNames->put((void*) name, fTargetNSURI, icKey); // ----------------------------------------------------------------------- // Get selector and fields // ----------------------------------------------------------------------- if (!traverseIdentityConstraint(icKey, icElem)) { fIdentityConstraintNames->put((void*) name, fTargetNSURI, 0); return; } // ----------------------------------------------------------------------- // Add key to element declaration // ----------------------------------------------------------------------- elemDecl->addIdentityConstraint(icKey); icKey->setNamespaceURI(fTargetNSURI); janKey.orphan(); } /** * */ void TraverseSchema::traverseUnique(const DOMElement* const icElem, SchemaElementDecl* const elemDecl) { NamespaceScopeManager nsMgr(icElem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( icElem, GeneralAttributeCheck::E_Unique, this, false, fNonXSAttList ); // ----------------------------------------------------------------------- // Create identity constraint // ----------------------------------------------------------------------- const XMLCh* name = getElementAttValue(icElem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_UNIQUE, name); return; } if (!fIdentityConstraintNames) { fIdentityConstraintNames = new (fGrammarPoolMemoryManager) RefHash2KeysTableOf(29, (bool) false, fGrammarPoolMemoryManager); } else if (fIdentityConstraintNames->containsKey(name, fTargetNSURI)) { reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_DuplicateDecl, name); return; } IC_Unique* icUnique = new (fGrammarPoolMemoryManager) IC_Unique(name, elemDecl->getBaseName(), fGrammarPoolMemoryManager); Janitor janUnique(icUnique); fIdentityConstraintNames->put((void*) name, fTargetNSURI, icUnique); // ----------------------------------------------------------------------- // Get selector and fields // ----------------------------------------------------------------------- if (!traverseIdentityConstraint(icUnique, icElem)) { fIdentityConstraintNames->put((void*) name, fTargetNSURI, 0); return; } // ----------------------------------------------------------------------- // Add identity cosntraints to element declaration // ----------------------------------------------------------------------- elemDecl->addIdentityConstraint(icUnique); icUnique->setNamespaceURI(fTargetNSURI); janUnique.orphan(); } /** * */ void TraverseSchema::traverseKeyRef(const DOMElement* const icElem, SchemaElementDecl* const elemDecl) { NamespaceScopeManager nsMgr(icElem, fSchemaInfo, this); // ----------------------------------------------------------------------- // Check Attributes // ----------------------------------------------------------------------- fAttributeCheck.checkAttributes( icElem, GeneralAttributeCheck::E_KeyRef, this, false, fNonXSAttList ); // ----------------------------------------------------------------------- // Verify that key reference "refer" attribute is valid // ----------------------------------------------------------------------- const XMLCh* name = getElementAttValue(icElem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); const XMLCh* refer = getElementAttValue(icElem, SchemaSymbols::fgATT_REFER, DatatypeValidator::QName); if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) { reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_KEYREF, name); return; } const XMLCh* prefix = getPrefix(refer); const XMLCh* localPart = getLocalPart(refer); // we use the DOM API, as the NamespaceScope is now pointing to a different place const XMLCh* uriStr = icElem->lookupNamespaceURI(*prefix==0?NULL:prefix); if ((!uriStr || !*uriStr) && (prefix && *prefix)) reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::UnresolvedPrefix, prefix); if(!uriStr) uriStr=XMLUni::fgZeroLenString; IdentityConstraint* icKey = (fIdentityConstraintNames) ? fIdentityConstraintNames->get(localPart, fURIStringPool->addOrFind(uriStr)) : 0; if (!icKey) { reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_KeyRefReferNotFound, name, localPart); return; } // ----------------------------------------------------------------------- // Create identity constraint // ----------------------------------------------------------------------- if(fIdentityConstraintNames->containsKey(name, fTargetNSURI)) { reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_DuplicateDecl, name); return; } IC_KeyRef* icKeyRef = new (fGrammarPoolMemoryManager) IC_KeyRef(name, elemDecl->getBaseName(), icKey, fGrammarPoolMemoryManager); Janitor janKeyRef(icKeyRef); fIdentityConstraintNames->put((void*) name, fTargetNSURI, icKeyRef); // ----------------------------------------------------------------------- // Get selector and fields // ----------------------------------------------------------------------- if (!traverseIdentityConstraint(icKeyRef, icElem)) { fIdentityConstraintNames->put((void*) name, fTargetNSURI, 0); return; } // ----------------------------------------------------------------------- // Add key reference to element decl // ----------------------------------------------------------------------- if (icKeyRef->getFieldCount() != icKey->getFieldCount()) { fIdentityConstraintNames->put((void*) name, fTargetNSURI, 0); reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_KeyRefCardinality, name, icKey->getIdentityConstraintName()); } else { elemDecl->addIdentityConstraint(icKeyRef); icKeyRef->setNamespaceURI(fTargetNSURI); janKeyRef.orphan(); } } bool TraverseSchema::traverseIdentityConstraint(IdentityConstraint* const ic, const DOMElement* const icElem) { NamespaceScopeManager nsMgr(icElem, fSchemaInfo, this); // ------------------------------------------------------------------ // First, handle any ANNOTATION declaration // ------------------------------------------------------------------ DOMElement* elem = checkContent(icElem, XUtil::getFirstChildElement(icElem), false); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(icElem, fNonXSAttList); } Janitor janAnnot(fAnnotation); // ------------------------------------------------------------------ // Get selector // ------------------------------------------------------------------ if (elem == 0) { // reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_BadContent); return false; } if (!XMLString::equals(elem->getLocalName(), SchemaSymbols::fgELT_SELECTOR)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::IC_BadContent); return false; } fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_Selector, this, false, fNonXSAttList ); if (checkContent(icElem, XUtil::getFirstChildElement(elem), true) != 0) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } if (fAnnotation) { if (janAnnot.isDataNull()) janAnnot.reset(fAnnotation); else janAnnot.get()->setNext(fAnnotation); } // ------------------------------------------------------------------ // Get xpath attribute // ------------------------------------------------------------------ const XMLCh* xpathExpr = getElementAttValue(elem, SchemaSymbols::fgATT_XPATH); XMLSize_t xpathLen = XMLString::stringLen(xpathExpr); if (!xpathExpr || !xpathLen) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::IC_XPathExprMissing); return false; } // ------------------------------------------------------------------ // Parse xpath expression // ------------------------------------------------------------------ try { XercesXPath* sXPath = new (fGrammarPoolMemoryManager) XercesXPath(xpathExpr, fStringPool, fSchemaInfo->getNamespaceScope(), fEmptyNamespaceURI, true, fGrammarPoolMemoryManager); IC_Selector* icSelector = new (fGrammarPoolMemoryManager) IC_Selector(sXPath, ic); ic->setSelector(icSelector); } catch (const XPathException& e) { reportSchemaError(elem, e); return false; } // ------------------------------------------------------------------ // Get fields // ------------------------------------------------------------------ elem = XUtil::getNextSiblingElement(elem); if (elem == 0) { reportSchemaError(icElem, XMLUni::fgXMLErrDomain, XMLErrs::IC_BadContent); return false; } while (elem != 0) { if (!XMLString::equals(elem->getLocalName(), SchemaSymbols::fgELT_FIELD)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::IC_BadContent); } else { // General Attribute Checking fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_Field, this, false, fNonXSAttList ); if (checkContent(icElem, XUtil::getFirstChildElement(elem), true) != 0) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected); if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size()) { fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList); } if (fAnnotation) { if (janAnnot.isDataNull()) janAnnot.reset(fAnnotation); else janAnnot.get()->setNext(fAnnotation); } // xpath expression parsing xpathExpr = getElementAttValue(elem, SchemaSymbols::fgATT_XPATH); if (!xpathExpr || !*xpathExpr) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::IC_XPathExprMissing); return false; } try { XercesXPath* fieldXPath = new (fGrammarPoolMemoryManager) XercesXPath ( xpathExpr , fStringPool , fSchemaInfo->getNamespaceScope() , fEmptyNamespaceURI , false , fGrammarPoolMemoryManager ); IC_Field* icField = new (fGrammarPoolMemoryManager) IC_Field(fieldXPath, ic); ic->addField(icField); } catch (const XPathException& e) { reportSchemaError(elem, e); return false; } } elem = XUtil::getNextSiblingElement(elem); } if (!janAnnot.isDataNull()) fSchemaGrammar->putAnnotation(ic, janAnnot.release()); if (ic->getFieldCount() == 0) { return false; } return true; } // --------------------------------------------------------------------------- // TraverseSchema: Helper methods // --------------------------------------------------------------------------- bool TraverseSchema::retrieveNamespaceMapping(const DOMElement* const elem) { DOMNamedNodeMap* eltAttrs = elem->getAttributes(); bool seenNS=false; const XMLSize_t attrCount = eltAttrs->getLength(); for (XMLSize_t i = 0; i < attrCount; i++) { DOMNode* attribute = eltAttrs->item(i); if (!attribute) { break; } const XMLCh* attName = attribute->getNodeName(); // starts with 'xmlns:' if (XMLString::startsWith(attName, XMLUni::fgXMLNSColonString)) { if(!seenNS) fSchemaInfo->getNamespaceScope()->increaseDepth(); seenNS=true; int offsetIndex = XMLString::indexOf(attName, chColon); const XMLCh* attValue = attribute->getNodeValue(); fSchemaInfo->getNamespaceScope()->addPrefix(attName + offsetIndex + 1, fURIStringPool->addOrFind(attValue)); } else if (XMLString::equals(attName, XMLUni::fgXMLNSString)) { // == 'xmlns' if(!seenNS) fSchemaInfo->getNamespaceScope()->increaseDepth(); seenNS=true; const XMLCh* attValue = attribute->getNodeValue(); fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgZeroLenString, fURIStringPool->addOrFind(attValue)); } } // end for return seenNS; } void TraverseSchema::processChildren(const DOMElement* const root) { NamespaceScopeManager nsMgr(root, fSchemaInfo, this); bool sawAnnotation = false; // process , and info items. DOMElement* child = XUtil::getFirstChildElement(root); for (; child != 0; child = XUtil::getNextSiblingElement(child)) { const XMLCh* name = child->getLocalName(); if (XMLString::equals(name, SchemaSymbols::fgELT_ANNOTATION)) { XSAnnotation* annot = traverseAnnotationDecl( child, fSchemaInfo->getNonXSAttList(), true); if (annot) { fSchemaGrammar->addAnnotation(annot); sawAnnotation = true; } } else if (XMLString::equals(name, SchemaSymbols::fgELT_INCLUDE)) { traverseInclude(child); } else if (XMLString::equals(name, SchemaSymbols::fgELT_IMPORT)) { traverseImport(child); } else if (XMLString::equals(name, SchemaSymbols::fgELT_REDEFINE)) { traverseRedefine(child); } else break; } // child refers to the first info item which is not or // one of the schema inclusion/importation declarations. for (; child != 0; child = XUtil::getNextSiblingElement(child)) { const XMLCh* name = child->getLocalName(); const XMLCh* typeName = getElementAttValue(child, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); int fullNameId = 0; if (typeName) { fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(typeName); fullNameId = fStringPool->addOrFind(fBuffer.getRawBuffer()); } if (XMLString::equals(name, SchemaSymbols::fgELT_ANNOTATION)) { XSAnnotation* annot = traverseAnnotationDecl( child, fSchemaInfo->getNonXSAttList(), true); if (annot) { fSchemaGrammar->addAnnotation(annot); sawAnnotation = true; } } else if (XMLString::equals(name, SchemaSymbols::fgELT_SIMPLETYPE)) { if (typeName && *typeName) { if (fGlobalDeclarations[ENUM_ELT_SIMPLETYPE]->containsElement(fullNameId) || fGlobalDeclarations[ENUM_ELT_COMPLEXTYPE]->containsElement(fullNameId)) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalType, SchemaSymbols::fgELT_SIMPLETYPE, typeName, SchemaSymbols::fgELT_COMPLEXTYPE); continue; } else { fGlobalDeclarations[ENUM_ELT_SIMPLETYPE]->addElement(fullNameId); } } traverseSimpleTypeDecl(child); } else if (XMLString::equals(name, SchemaSymbols::fgELT_COMPLEXTYPE)) { if (typeName && *typeName) { if (fGlobalDeclarations[ENUM_ELT_SIMPLETYPE]->containsElement(fullNameId) || fGlobalDeclarations[ENUM_ELT_COMPLEXTYPE]->containsElement(fullNameId)) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalType, SchemaSymbols::fgELT_COMPLEXTYPE, typeName, SchemaSymbols::fgELT_SIMPLETYPE); continue; } else { fGlobalDeclarations[ENUM_ELT_COMPLEXTYPE]->addElement(fullNameId); } } traverseComplexTypeDecl(child); } else if (XMLString::equals(name, SchemaSymbols::fgELT_ELEMENT)) { if (typeName && *typeName) { if (fGlobalDeclarations[ENUM_ELT_ELEMENT]->containsElement(fullNameId)) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalDeclaration, SchemaSymbols::fgELT_ELEMENT, typeName); continue; } else { fGlobalDeclarations[ENUM_ELT_ELEMENT]->addElement(fullNameId); } } traverseElementDecl(child, true); } else if (XMLString::equals(name, SchemaSymbols::fgELT_ATTRIBUTEGROUP)) { if (typeName && *typeName) { if (fGlobalDeclarations[ENUM_ELT_ATTRIBUTEGROUP]->containsElement(fullNameId)) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalDeclaration, SchemaSymbols::fgELT_ATTRIBUTEGROUP, typeName); continue; } else { fGlobalDeclarations[ENUM_ELT_ATTRIBUTEGROUP]->addElement(fullNameId); } } if (!typeName || !fAttGroupRegistry->containsKey(typeName)) { traverseAttributeGroupDecl(child, 0, true); } } else if (XMLString::equals(name, SchemaSymbols::fgELT_ATTRIBUTE)) { if (typeName && *typeName) { if (fGlobalDeclarations[ENUM_ELT_ATTRIBUTE]->containsElement(fullNameId)) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, typeName); continue; } else { fGlobalDeclarations[ENUM_ELT_ATTRIBUTE]->addElement(fullNameId); } } if (!typeName || !fAttributeDeclRegistry->containsKey(typeName)) { traverseAttributeDecl( child, 0, true); } } else if (XMLString::equals(name, SchemaSymbols::fgELT_GROUP)) { if (typeName && *typeName) { if (fGlobalDeclarations[ENUM_ELT_GROUP]->containsElement(fullNameId)) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateGlobalDeclaration, SchemaSymbols::fgELT_GROUP, typeName); continue; } else { fGlobalDeclarations[ENUM_ELT_GROUP]->addElement(fullNameId); } } if (!typeName || !fGroupRegistry->containsKey(fBuffer.getRawBuffer())) { traverseGroupDecl(child); } } else if (XMLString::equals(name, SchemaSymbols::fgELT_NOTATION)) { traverseNotationDecl(child); } else { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::SchemaElementContentError); } } // for each child node if (fScanner->getGenerateSyntheticAnnotations() && fSchemaInfo->getNonXSAttList()->size() && !sawAnnotation) { // synthesize a global annotation here. fSchemaGrammar->addAnnotation( generateSyntheticAnnotation(root, fSchemaInfo->getNonXSAttList()) ); } // Handle recursing elements - if any ValueVectorOf* recursingAnonTypes = fSchemaInfo->getRecursingAnonTypes(); if (recursingAnonTypes) { ValueVectorOf* recursingTypeNames = fSchemaInfo->getRecursingTypeNames(); XMLSize_t recurseSize = recursingAnonTypes->size(); for (XMLSize_t i=0; i < recurseSize; i++) { traverseComplexTypeDecl(recursingAnonTypes->elementAt(i), false, recursingTypeNames->elementAt(i)); } recursingAnonTypes->removeAllElements(); recursingTypeNames->removeAllElements(); } } void TraverseSchema::preprocessChildren(const DOMElement* const root) { NamespaceScopeManager nsMgr(root, fSchemaInfo, this); // process , and info items. DOMElement* child = XUtil::getFirstChildElement(root); for (; child != 0; child = XUtil::getNextSiblingElement(child)) { const XMLCh* name = child->getLocalName(); if (XMLString::equals(name, SchemaSymbols::fgELT_ANNOTATION)) { continue; } else if (XMLString::equals(name, SchemaSymbols::fgELT_INCLUDE)) { preprocessInclude(child); } else if (XMLString::equals(name, SchemaSymbols::fgELT_IMPORT)) { preprocessImport(child); } else if (XMLString::equals(name, SchemaSymbols::fgELT_REDEFINE)) { preprocessRedefine(child); } else break; } } DOMElement* TraverseSchema::checkContent( const DOMElement* const rootElem , DOMElement* const contentElem , const bool isEmpty , const bool processAnnot) { DOMElement* content = contentElem; const XMLCh* name = getElementAttValue(rootElem,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); fAnnotation = 0; Janitor janAnnot(0); if (!content) { if (!isEmpty) { reportSchemaError(rootElem, XMLUni::fgXMLErrDomain, XMLErrs::ContentError, name); } return 0; } if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { if (processAnnot) { janAnnot.reset(traverseAnnotationDecl(content, fNonXSAttList)); } content = XUtil::getNextSiblingElement(content); if (!content) { // must be followed by content if (!isEmpty) { reportSchemaError(contentElem, XMLUni::fgXMLErrDomain, XMLErrs::ContentError, name); } fAnnotation = janAnnot.release(); return 0; } if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AnnotationError, name); return 0; } fAnnotation = janAnnot.release(); } return content; } DatatypeValidator* TraverseSchema::getDatatypeValidator(const XMLCh* const uriStr, const XMLCh* const localPartStr) { DatatypeValidator* dv = 0; if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { dv = fDatatypeRegistry->getDatatypeValidator(localPartStr); } else { fBuffer.set(uriStr); fBuffer.append(chComma); fBuffer.append(localPartStr); if ((uriStr) && !XMLString::equals(uriStr, fTargetNSURIString)) { Grammar* grammar = fGrammarResolver->getGrammar(uriStr); if (grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) { dv = ((SchemaGrammar*) grammar)->getDatatypeRegistry()->getDatatypeValidator(fBuffer.getRawBuffer()); } } else { dv = fDatatypeRegistry->getDatatypeValidator(fBuffer.getRawBuffer()); } } return dv; } DatatypeValidator* TraverseSchema::checkForSimpleTypeValidator(const DOMElement* const content, int baseRefContext) { DatatypeValidator* baseValidator = traverseSimpleTypeDecl(content, false, baseRefContext); if (!baseValidator) { const XMLCh* name = getElementAttValue(content,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::UnknownSimpleType, name); } return baseValidator; } ComplexTypeInfo* TraverseSchema::checkForComplexTypeInfo(const DOMElement* const content) { int typeNameIndex = traverseComplexTypeDecl(content, false); ComplexTypeInfo* baseTypeInfo = 0; if (typeNameIndex != -1) { baseTypeInfo = fComplexTypeRegistry->get(fStringPool->getValueForId(typeNameIndex)); } if (typeNameIndex == -1 || baseTypeInfo == 0) { const XMLCh* name = getElementAttValue(content,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::UnknownComplexType, name); } return baseTypeInfo; } DatatypeValidator* TraverseSchema::findDTValidator(const DOMElement* const elem, const XMLCh* const derivedTypeName, const XMLCh* const baseTypeName, const int baseRefContext) { const XMLCh* prefix = getPrefix(baseTypeName); const XMLCh* localPart = getLocalPart(baseTypeName); const XMLCh* uri = resolvePrefixToURI(elem, prefix); DatatypeValidator* baseValidator = getDatatypeValidator(uri, localPart); if (baseValidator == 0) { // Check if the base is from the schema for schema namespace // if (XMLString::equals(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uri, localPart); return 0; } SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; SchemaInfo* saveInfo = fSchemaInfo; unsigned int saveScope = fCurrentScope; if (!XMLString::equals(uri, fTargetNSURIString) && (uri && *uri)) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(uri); if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uri); return 0; } SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uri, localPart); return 0; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } DOMElement* baseTypeNode = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_SimpleType, SchemaSymbols::fgELT_SIMPLETYPE, localPart, &fSchemaInfo); if (baseTypeNode != 0) { baseValidator = traverseSimpleTypeDecl(baseTypeNode); // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } } } if (baseValidator == 0) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::UnknownBaseDatatype, baseTypeName, derivedTypeName); } else if ((baseValidator->getFinalSet() & baseRefContext) != 0) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DisallowedBaseDerivation, baseTypeName); return 0; } return baseValidator; } const XMLCh* TraverseSchema::resolvePrefixToURI(const DOMElement* const elem, const XMLCh* const prefix) { unsigned int nameSpaceIndex = fSchemaInfo->getNamespaceScope()->getNamespaceForPrefix(prefix); const XMLCh* uriStr = fURIStringPool->getValueForId(nameSpaceIndex); if ((!uriStr || !*uriStr) && (prefix && *prefix)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::UnresolvedPrefix, prefix); return XMLUni::fgZeroLenString; } return uriStr; } SchemaElementDecl* TraverseSchema::processElementDeclRef(const DOMElement* const elem, const XMLCh* const refName) { // check attributes fAttributeCheck.checkAttributes( elem, GeneralAttributeCheck::E_ElementRef, this, false, fNonXSAttList ); // handle annotation DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); Janitor janAnnot(fAnnotation); // do not generate synthetic annotation for element reference... if (content != 0) reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::NoContentForRef, SchemaSymbols::fgELT_ELEMENT); SchemaElementDecl* refElemDecl = getGlobalElemDecl(elem, refName); if (!refElemDecl) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::RefElementNotFound, refName); } else { if (fCurrentComplexType) fCurrentComplexType->addElement(refElemDecl); if (fCurrentGroupInfo) fCurrentGroupInfo->addElement(refElemDecl); } return refElemDecl; } int TraverseSchema::parseBlockSet(const DOMElement* const elem, const int blockType, const bool isRoot) { const XMLCh* blockVal = (isRoot) ? getElementAttValue(elem, SchemaSymbols::fgATT_BLOCKDEFAULT) : getElementAttValue(elem, SchemaSymbols::fgATT_BLOCK); // blockVal == 0 means 'block attribute is missing'; *blockVal == 0 means 'block="" found' if (blockVal == 0) return fSchemaInfo->getBlockDefault(); int blockSet = 0; if (XMLString::equals(blockVal, SchemaSymbols::fgATTVAL_POUNDALL)) { blockSet = SchemaSymbols::XSD_EXTENSION + SchemaSymbols::XSD_RESTRICTION + SchemaSymbols::XSD_SUBSTITUTION; return blockSet; } XMLStringTokenizer tokenizer(blockVal, fGrammarPoolMemoryManager); while (tokenizer.hasMoreTokens()) { XMLCh* token = tokenizer.nextToken(); if (XMLString::equals(token, SchemaSymbols::fgATTVAL_SUBSTITUTION) && blockType == ES_Block) { if ((blockSet & SchemaSymbols::XSD_SUBSTITUTION) == 0 ) { blockSet += SchemaSymbols::XSD_SUBSTITUTION; } } else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_EXTENSION)) { if ((blockSet & SchemaSymbols::XSD_EXTENSION) == 0) { blockSet += SchemaSymbols::XSD_EXTENSION; } } else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_RESTRICTION)) { if ((blockSet & SchemaSymbols::XSD_RESTRICTION) == 0 ) { blockSet += SchemaSymbols::XSD_RESTRICTION; } } else { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidBlockValue, blockVal); } } //end while return blockSet; } int TraverseSchema::parseFinalSet(const DOMElement* const elem, const int finalType, const bool isRoot) { const XMLCh* finalVal = (isRoot) ? getElementAttValue(elem, SchemaSymbols::fgATT_FINALDEFAULT) : getElementAttValue(elem, SchemaSymbols::fgATT_FINAL); // finalVal == 0 means 'final attribute is missing'; *finalVal == 0 means 'final="" found' if (finalVal == 0) return fSchemaInfo->getFinalDefault(); int finalSet = 0; if (XMLString::equals(finalVal, SchemaSymbols::fgATTVAL_POUNDALL)) { finalSet = SchemaSymbols::XSD_RESTRICTION + SchemaSymbols::XSD_LIST + SchemaSymbols::XSD_UNION + SchemaSymbols::XSD_EXTENSION; return finalSet; } XMLStringTokenizer tokenizer(finalVal, fGrammarPoolMemoryManager); while (tokenizer.hasMoreTokens()) { XMLCh* token = tokenizer.nextToken(); if (XMLString::equals(token, SchemaSymbols::fgELT_UNION) && (finalType == S_Final || finalType == ECS_Final)) { if ((finalSet & SchemaSymbols::XSD_UNION) == 0) { finalSet += SchemaSymbols::XSD_UNION; } } else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_EXTENSION) && (finalType == EC_Final || finalType == ECS_Final)) { if ((finalSet & SchemaSymbols::XSD_EXTENSION) == 0) { finalSet += SchemaSymbols::XSD_EXTENSION; } } else if (XMLString::equals(token, SchemaSymbols::fgELT_LIST) && (finalType == S_Final || finalType == ECS_Final)) { if ((finalSet & SchemaSymbols::XSD_LIST) == 0 ) { finalSet += SchemaSymbols::XSD_LIST; } } else if (XMLString::equals(token, SchemaSymbols::fgATTVAL_RESTRICTION)) { if ((finalSet & SchemaSymbols::XSD_RESTRICTION) == 0 ) { finalSet += SchemaSymbols::XSD_RESTRICTION; } } else { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidFinalValue, finalVal); } } //end while return finalSet; } const DOMElement* TraverseSchema::checkIdentityConstraintContent(const DOMElement* const content) { const DOMElement* child = content; if (child != 0) { do { if (!isIdentityConstraintName(child->getLocalName())) { break; } child = XUtil::getNextSiblingElement(child); } while (child != 0); } return child; } bool TraverseSchema::isIdentityConstraintName(const XMLCh* const name) { return (XMLString::equals(name, SchemaSymbols::fgELT_KEY) || XMLString::equals(name, SchemaSymbols::fgELT_KEYREF) || XMLString::equals(name, SchemaSymbols::fgELT_UNIQUE)); } const XMLCh* TraverseSchema::checkTypeFromAnotherSchema(const DOMElement* const elem, const XMLCh* const typeStr) { const XMLCh* prefix = getPrefix(typeStr); const XMLCh* typeURI = resolvePrefixToURI(elem, prefix); if (!XMLString::equals(typeURI, fTargetNSURIString) && !XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) ) { return typeURI; } return 0; } DatatypeValidator* TraverseSchema::getElementTypeValidator(const DOMElement* const elem, const XMLCh* const typeStr, bool& noErrorDetected, const XMLCh* const otherSchemaURI) { const XMLCh* localPart = getLocalPart(typeStr); const XMLCh* typeURI = otherSchemaURI; DatatypeValidator* dv = 0; SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; SchemaInfo* saveInfo = fSchemaInfo; unsigned int saveScope = fCurrentScope; if (otherSchemaURI && *otherSchemaURI) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(otherSchemaURI); if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, otherSchemaURI); return 0; } dv = getDatatypeValidator(typeURI, localPart); if (dv) { return dv; } SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, typeURI, localPart); return 0; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } else { const XMLCh* prefix = getPrefix(typeStr); typeURI = resolvePrefixToURI(elem, prefix); dv = getDatatypeValidator(typeURI, localPart); } if (!dv) { if (!XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) || XMLString::equals(fTargetNSURIString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { DOMElement* typeElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_SimpleType, SchemaSymbols::fgELT_SIMPLETYPE, localPart, &fSchemaInfo); if (typeElem) { traverseSimpleTypeDecl(typeElem); dv = getDatatypeValidator(typeURI, localPart); } } // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } if (!dv) { noErrorDetected = false; reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, typeURI, localPart); } } return dv; } DatatypeValidator* TraverseSchema::getAttrDatatypeValidatorNS(const DOMElement* const elem, const XMLCh* localPart, const XMLCh* typeURI) { DatatypeValidator* dv = getDatatypeValidator(typeURI, localPart); SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; SchemaInfo* saveInfo = fSchemaInfo; unsigned int saveScope = fCurrentScope; if (!XMLString::equals(typeURI, fTargetNSURIString) && (typeURI && *typeURI)) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(typeURI); if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, typeURI); return 0; } if (!dv) { SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, typeURI, localPart); return 0; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } } if (!dv) { DOMElement* typeElem = fSchemaInfo->getTopLevelComponent ( SchemaInfo::C_SimpleType , SchemaSymbols::fgELT_SIMPLETYPE , localPart , &fSchemaInfo ); if (typeElem) dv = traverseSimpleTypeDecl(typeElem); // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } } return dv; } ComplexTypeInfo* TraverseSchema::getElementComplexTypeInfo(const DOMElement* const elem, const XMLCh* const typeStr, const XMLCh* const otherSchemaURI) { const XMLCh* localPart = getLocalPart(typeStr); const XMLCh* prefix = getPrefix(typeStr); const XMLCh* typeURI = (otherSchemaURI) ? otherSchemaURI : resolvePrefixToURI(elem, prefix); ComplexTypeInfo* typeInfo = 0; SchemaInfo* saveInfo = fSchemaInfo; SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; unsigned int saveScope = fCurrentScope; fBuffer.set(typeURI); fBuffer.append(chComma); fBuffer.append(localPart); if (otherSchemaURI != 0) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(typeURI); if (!isImportingNS(uriId)) return 0; Grammar* aGrammar = fGrammarResolver->getGrammar(typeURI); if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) { return 0; } typeInfo = ((SchemaGrammar*)aGrammar)->getComplexTypeRegistry()->get(fBuffer.getRawBuffer()); if (typeInfo) { return typeInfo; } SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); if (!impInfo || impInfo->getProcessed()) { return 0; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } else { typeInfo = fComplexTypeRegistry->get(fBuffer.getRawBuffer()); } if (!typeInfo) { if (!XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) || XMLString::equals(fTargetNSURIString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { DOMElement* typeNode = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_ComplexType, SchemaSymbols::fgELT_COMPLEXTYPE, localPart, &fSchemaInfo); if (typeNode) { // fBuffer is reused by traverseComplexTypeDecl, so we have to store its current value XMLBuffer buffCopy(fBuffer.getLen()+1, fMemoryManager); buffCopy.set(fBuffer.getRawBuffer()); traverseComplexTypeDecl(typeNode); typeInfo = fComplexTypeRegistry->get(buffCopy.getRawBuffer()); } } } // restore schema information restoreSchemaInfo(saveInfo, infoType, saveScope); return typeInfo; } SchemaElementDecl* TraverseSchema::getGlobalElemDecl(const DOMElement* const elem, const XMLCh* const qName) { const XMLCh* nameURI = resolvePrefixToURI(elem, getPrefix(qName)); const XMLCh* localPart = getLocalPart(qName); SchemaElementDecl* elemDecl = 0; SchemaInfo* saveInfo = fSchemaInfo; SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; unsigned int saveScope = fCurrentScope; unsigned int uriId = fURIStringPool->addOrFind(nameURI); if (fSchemaInfo->getTargetNSURI() != (int) uriId) { //if (!XMLString::equals(nameURI, fTargetNSURIString)) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, nameURI); return 0; } Grammar* grammar = fGrammarResolver->getGrammar(nameURI); if (grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) { elemDecl = (SchemaElementDecl*) grammar->getElemDecl( uriId, localPart, 0, Grammar::TOP_LEVEL_SCOPE); } else { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, nameURI); return 0; } if (!elemDecl) { SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, nameURI, localPart); return 0; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } } else { elemDecl = (SchemaElementDecl*) fSchemaGrammar->getElemDecl(fTargetNSURI, localPart, 0, Grammar::TOP_LEVEL_SCOPE); } if (!elemDecl) { DOMElement* subsGroupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Element, SchemaSymbols::fgELT_ELEMENT,localPart, &fSchemaInfo); if (subsGroupElem) elemDecl = traverseElementDecl(subsGroupElem, true); if (!elemDecl) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, nameURI, localPart); } // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } return elemDecl; } bool TraverseSchema::isSubstitutionGroupValid(const DOMElement* const elem, const SchemaElementDecl* const subsElemDecl, const ComplexTypeInfo* const typeInfo, const DatatypeValidator* const validator, const XMLCh* const elemName, const bool toEmit) { // here we must do two things: // 1. Make sure there actually *is* a relation between the types of // the element being nominated and the element doing the nominating; // (see PR 3.3.6 point #3 in the first tableau, for instance; this // and the corresponding tableaux from 3.4.6 and 3.14.6 rule out the nominated // element having an anonymous type declaration. // 2. Make sure the nominated element allows itself to be nominated by // an element with the given type-relation. // Note: we assume that (complex|simple)Type processing checks // whether the type in question allows itself to // be modified as this element desires. // if substitution element has any as content model type, return true bool subsRestricted = false; if (subsElemDecl->getModelType() == SchemaElementDecl::Any) { if ((subsElemDecl->getFinalSet() & SchemaSymbols::XSD_RESTRICTION) == 0 || (typeInfo == 0 && validator == 0)) return true; else subsRestricted = true; } // Check for type relationship; // that is, make sure that the type we're deriving has some relatoinship // to substitutionGroupElt's type. else if (typeInfo) { // do complexType case ...need testing ComplexTypeInfo* subsTypeInfo = subsElemDecl->getComplexTypeInfo(); if (subsTypeInfo == typeInfo) return true; int derivationMethod = typeInfo->getDerivedBy(); if (subsTypeInfo == 0) { // take care of complexType based on simpleType case... DatatypeValidator* elemDV = typeInfo->getDatatypeValidator(); DatatypeValidator* subsValidator = subsElemDecl->getDatatypeValidator(); if (elemDV == subsValidator) { return true; } else if (subsValidator && subsValidator->isSubstitutableBy(elemDV)) { if ((subsElemDecl->getFinalSet() & derivationMethod) == 0) { return true; } else { subsRestricted = true; } } } else { // complex content const ComplexTypeInfo* elemTypeInfo = typeInfo; for (; elemTypeInfo && elemTypeInfo != subsTypeInfo; elemTypeInfo = elemTypeInfo->getBaseComplexTypeInfo()) { } if (elemTypeInfo) { if ((subsElemDecl->getFinalSet() & derivationMethod) == 0) { return true; } else { subsRestricted = true; } } } } else if (validator) { // do simpleType case... if (!subsElemDecl->getComplexTypeInfo()) { // first, check for type relation. DatatypeValidator* subsValidator = subsElemDecl->getDatatypeValidator(); if (subsValidator == validator) { return true; } else if (subsValidator && subsValidator->isSubstitutableBy(validator) && ((subsElemDecl->getFinalSet() & SchemaSymbols::XSD_RESTRICTION) == 0)) { return true; } } } else // validator==0 && typeInfo==0 -- no checking return true; if (toEmit) { if (subsRestricted) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidSubstitutionGroupElement, elemName, subsElemDecl->getBaseName()); } else { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::SubstitutionGroupTypeMismatch, elemName); } } return false; } SchemaElementDecl* TraverseSchema::createSchemaElementDecl(const DOMElement* const elem, const XMLCh* const name, bool& isDuplicate, const XMLCh*& valConstraint, const bool topLevel) { unsigned int enclosingScope = fCurrentScope; int uriIndex = fEmptyNamespaceURI; if (topLevel) { uriIndex = fTargetNSURI; enclosingScope = Grammar::TOP_LEVEL_SCOPE; } else { const XMLCh* elemForm = getElementAttValue(elem, SchemaSymbols::fgATT_FORM); if (((!elemForm || !*elemForm) && (fSchemaInfo->getElemAttrDefaultQualified() & Elem_Def_Qualified)) || XMLString::equals(elemForm,SchemaSymbols::fgATTVAL_QUALIFIED)) uriIndex = fTargetNSURI; // Check for duplicate elements SchemaElementDecl* other = (SchemaElementDecl*) fSchemaGrammar->getElemDecl(uriIndex, name, 0, enclosingScope); if (other != 0) { isDuplicate = true; return other; } } // create element decl and add it to the grammar Janitor elemDecl(new (fGrammarPoolMemoryManager) SchemaElementDecl( XMLUni::fgZeroLenString , name, uriIndex , SchemaElementDecl::Any , enclosingScope , fGrammarPoolMemoryManager )); elemDecl->setCreateReason(XMLElementDecl::Declared); if (topLevel) elemDecl->setPSVIScope(PSVIDefs::SCP_GLOBAL); // process attributes processElemDeclAttrs(elem, elemDecl.get(), valConstraint, topLevel); return elemDecl.release(); } void TraverseSchema::processAttributeDeclRef(const DOMElement* const elem, ComplexTypeInfo* const typeInfo, const XMLCh* const refName, const XMLCh* const useAttr, const XMLCh* const defaultVal, const XMLCh* const fixedVal) { if (!typeInfo && !fCurrentAttGroupInfo) { return; } const XMLCh* prefix = getPrefix(refName); const XMLCh* localPart = getLocalPart(refName); const XMLCh* uriStr = resolvePrefixToURI(elem, prefix); unsigned int attURI = fURIStringPool->addOrFind(uriStr); // Check for duplicate references if (typeInfo && typeInfo->getAttDef(localPart, attURI)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateRefAttribute, uriStr, localPart); return; } else if (fCurrentAttGroupInfo && fCurrentAttGroupInfo->containsAttribute(localPart, attURI)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateRefAttribute, uriStr, localPart); return; } // check for different namespace SchemaInfo* saveInfo = fSchemaInfo; SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; SchemaAttDef* refAttDef = 0; unsigned int saveScope = fCurrentScope; if (!XMLString::equals(uriStr, fTargetNSURIString)) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(uriStr); if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); return; } Grammar* grammar = fGrammarResolver->getGrammar(uriStr); if (grammar == 0 || grammar->getGrammarType() != Grammar::SchemaGrammarType) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); return; } refAttDef = (SchemaAttDef*) ((SchemaGrammar*) grammar)->getAttributeDeclRegistry()->get(localPart); if (!refAttDef) { SchemaInfo* impInfo = fSchemaInfo->getImportInfo(attURI); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelAttributeNotFound, refName); return; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } } // if Global attribute registry does not contain the ref attribute, get // the referred attribute declaration and traverse it. if (!refAttDef) { if (fAttributeDeclRegistry->containsKey(localPart) == false) { DOMElement* referredAttribute = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Attribute, SchemaSymbols::fgELT_ATTRIBUTE, localPart, &fSchemaInfo); if (referredAttribute != 0) { traverseAttributeDecl(referredAttribute, 0, true); } } refAttDef = (SchemaAttDef*) fAttributeDeclRegistry->get(localPart); } // restore schema information, if necessary if (fSchemaInfo != saveInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } if (!refAttDef) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelAttributeNotFound, refName); return; } XMLAttDef::DefAttTypes refAttDefType = refAttDef->getDefaultType(); const XMLCh* refAttValue = refAttDef->getValue(); bool invalidAttUse = false; if (refAttDefType == XMLAttDef::Fixed && (defaultVal || (fixedVal && !XMLString::equals(fixedVal, refAttValue)))) { invalidAttUse = true; reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttUseCorrect, refName); } DatatypeValidator* attDV = refAttDef->getDatatypeValidator(); //check for multiple attributes with type derived from ID if (attDV && attDV->getType() == DatatypeValidator::ID) { if (fCurrentAttGroupInfo) { if (fCurrentAttGroupInfo->containsTypeWithId()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, refName); return; } fCurrentAttGroupInfo->setTypeWithId(true); } else { if (typeInfo->containsAttWithTypeId()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, refName); return; } typeInfo->setAttWithTypeId(true); } } bool required = XMLString::equals(useAttr,SchemaSymbols::fgATTVAL_REQUIRED); bool prohibited = XMLString::equals(useAttr,SchemaSymbols::fgATTVAL_PROHIBITED); QName* attQName = refAttDef->getAttName(); SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef(attQName->getPrefix(), attQName->getLocalPart(), attQName->getURI(), refAttValue, refAttDef->getType(), refAttDefType, 0, fGrammarPoolMemoryManager); attDef->setBaseAttDecl(refAttDef); attDef->setPSVIScope(PSVIDefs::SCP_GLOBAL); if (refAttDefType == XMLAttDef::Fixed) { if (required && !invalidAttUse) { attDef->setDefaultType(XMLAttDef::Required_And_Fixed); } } else { if (prohibited) { attDef->setDefaultType(XMLAttDef::Prohibited); } else { const XMLCh* valueConstraint = defaultVal; if (required){ if (fixedVal) { attDef->setDefaultType(XMLAttDef::Required_And_Fixed); valueConstraint = fixedVal; } else { attDef->setDefaultType(XMLAttDef::Required); } } else { if (fixedVal) { attDef->setDefaultType(XMLAttDef::Fixed); valueConstraint = fixedVal; } else if (defaultVal) { attDef->setDefaultType(XMLAttDef::Default); } } if (valueConstraint) { // validate content of value constraint if (attDV) { if (attDV->getType() == DatatypeValidator::ID) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3, refName); } else { try { attDV->validate(valueConstraint , fSchemaInfo->getValidationContext() , fMemoryManager); } catch(const XMLException& excep) { reportSchemaError(elem, excep); } catch(const OutOfMemoryException&) { throw; } catch (...) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueConstraint); } } } attDef->setValue(valueConstraint); } } } attDef->setDatatypeValidator(attDV); bool toClone = false; if (typeInfo) { toClone = true; typeInfo->addAttDef(attDef); } if (fCurrentAttGroupInfo) { fCurrentAttGroupInfo->addAttDef(attDef, toClone); } } int TraverseSchema::checkMinMax(ContentSpecNode* const specNode, const DOMElement* const elem, const int allContextFlag) { int minOccurs = 1; int maxOccurs = 1; const XMLCh* minOccursStr = getElementAttValue(elem, SchemaSymbols::fgATT_MINOCCURS, DatatypeValidator::Decimal); const XMLCh* maxOccursStr = getElementAttValue(elem, SchemaSymbols::fgATT_MAXOCCURS, DatatypeValidator::Decimal); if (!minOccursStr || !*minOccursStr) { if (specNode) minOccurs = specNode->getMinOccurs(); } else { try { minOccurs = XMLString::parseInt(minOccursStr, fMemoryManager); } catch(const NumberFormatException& e) { // REVISIT: report a warning that we replaced a number too big? if(e.getCode()==XMLExcepts::Str_ConvertOverflow) minOccurs = 500; else minOccurs = 1; } catch(const OutOfMemoryException&) { throw; } if (specNode) specNode->setMinOccurs(minOccurs); } bool isMaxUnbounded = XMLString::equals(maxOccursStr, fgUnbounded); if (isMaxUnbounded) { maxOccurs = SchemaSymbols::XSD_UNBOUNDED; if (specNode) specNode->setMaxOccurs(maxOccurs); } else { if (!maxOccursStr || !*maxOccursStr) { if (specNode) maxOccurs = specNode->getMaxOccurs(); } else { try { maxOccurs = XMLString::parseInt(maxOccursStr, fMemoryManager); } catch(const NumberFormatException& e) { // REVISIT: report a warning that we replaced a number too big? if(e.getCode()==XMLExcepts::Str_ConvertOverflow && minOccurs < 500) maxOccurs = 500; else maxOccurs = minOccurs; } catch(const OutOfMemoryException&) { throw; } if (specNode) specNode->setMaxOccurs(maxOccurs); } } if (minOccurs == 0 && maxOccurs == 0){ return minOccurs; } // Constraint checking for min/max value if (!isMaxUnbounded) { XMLCh tmpMinStr[128]; XMLCh tmpMaxStr[128]; XMLString::binToText(minOccurs, tmpMinStr, 127, 10, fMemoryManager); XMLString::binToText(maxOccurs, tmpMaxStr, 127, 10, fMemoryManager); if (maxOccurs < 1) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttValue, tmpMaxStr, SchemaSymbols::fgATT_MAXOCCURS); if (specNode) specNode->setMaxOccurs(minOccurs); } else if (maxOccurs < minOccurs) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidMin2MaxOccurs, tmpMinStr, tmpMaxStr); if (specNode) specNode->setMaxOccurs(minOccurs); } } // Constraint checking for 'all' content bool isAllElement = (allContextFlag == All_Element); bool isAllGroup = (allContextFlag == All_Group); bool isGroupRefAll = (allContextFlag == Group_Ref_With_All); if (isAllElement || isAllGroup || isGroupRefAll) { if (maxOccurs != 1 || minOccurs > 1) { // set back correct value in order to carry on if (specNode) { specNode->setMaxOccurs(1); if (minOccurs > 1) specNode->setMinOccurs(1); } if (isAllElement) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadMinMaxAllElem); } else { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadMinMaxAllCT); } } } return minOccurs; } void TraverseSchema::processComplexContent(const DOMElement* const ctElem, const XMLCh* const typeName, const DOMElement* const childElem, ComplexTypeInfo* const typeInfo, const XMLCh* const baseLocalPart, const bool isMixed, const bool isBaseAnyType) { NamespaceScopeManager nsMgr(childElem, fSchemaInfo, this); Janitor specNodeJan(0); ContentSpecNode* specNode = specNodeJan.get(); const DOMElement* attrNode = 0; int typeDerivedBy = typeInfo->getDerivedBy(); ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo(); int baseContentType = (baseTypeInfo) ? baseTypeInfo->getContentType() : SchemaElementDecl::Empty; if (baseTypeInfo) { if (typeDerivedBy == SchemaSymbols::XSD_RESTRICTION) { // check to see if the baseType permits derivation by restriction if((baseTypeInfo->getFinalSet() & typeDerivedBy) != 0) { reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivationByRestriction, baseLocalPart); throw TraverseSchema::InvalidComplexTypeInfo; } } else { // check to see if the baseType permits derivation by extension if((baseTypeInfo->getFinalSet() & typeDerivedBy) != 0) { reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivationByExtension, baseLocalPart); throw TraverseSchema::InvalidComplexTypeInfo; // REVISIT - should we continue } processElements(ctElem, baseTypeInfo, typeInfo); } } bool effectiveContent_hasChild = false; if (childElem != 0) { fCircularCheckIndex = fCurrentTypeNameStack->size(); // -------------------------------------------------------------------- // GROUP, ALL, SEQUENCE or CHOICE, followed by attributes, if specified. // Note that it's possible that only attributes are specified. // -------------------------------------------------------------------- const XMLCh* childName = childElem->getLocalName(); if (XMLString::equals(childName, SchemaSymbols::fgELT_GROUP)) { XercesGroupInfo* grpInfo = traverseGroupDecl(childElem, false); if (grpInfo) { ContentSpecNode* const groupSpecNode = grpInfo->getContentSpec(); if (groupSpecNode) { int contentContext = groupSpecNode->hasAllContent() ? Group_Ref_With_All : Not_All_Context; specNodeJan.reset(new (fGrammarPoolMemoryManager) ContentSpecNode(*groupSpecNode)); specNode = specNodeJan.get(); checkMinMax(specNode, childElem, contentContext); } } attrNode = XUtil::getNextSiblingElement(childElem); } else if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) { specNodeJan.reset(traverseChoiceSequence(childElem, ContentSpecNode::Sequence, effectiveContent_hasChild)); specNode = specNodeJan.get(); checkMinMax(specNode, childElem); attrNode = XUtil::getNextSiblingElement(childElem); } else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) { specNodeJan.reset(traverseChoiceSequence(childElem, ContentSpecNode::Choice, effectiveContent_hasChild)); specNode = specNodeJan.get(); int minOccurs = checkMinMax(specNode, childElem); if (!effectiveContent_hasChild && minOccurs != 0) { effectiveContent_hasChild = true; } attrNode = XUtil::getNextSiblingElement(childElem); } else if (XMLString::equals(childName, SchemaSymbols::fgELT_ALL)) { specNodeJan.reset(traverseAll(childElem, effectiveContent_hasChild)); specNode = specNodeJan.get(); checkMinMax(specNode, childElem, All_Group); attrNode = XUtil::getNextSiblingElement(childElem); } else if (isAttrOrAttrGroup(childElem)) { // reset the contentType typeInfo->setContentType(SchemaElementDecl::Any); attrNode = childElem; } else { reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType, childName); } } typeInfo->setContentSpec(specNode); typeInfo->setAdoptContentSpec(true); specNodeJan.release(); bool specNodeWasNull = false; // ----------------------------------------------------------------------- // Merge in information from base, if it exists // ----------------------------------------------------------------------- if (baseTypeInfo) { ContentSpecNode* baseSpecNode = baseTypeInfo->getContentSpec(); if (typeDerivedBy == SchemaSymbols::XSD_RESTRICTION) { //check derivation valid - content type is empty (5.2) if (!typeInfo->getContentSpec()) { if (baseContentType != SchemaElementDecl::Empty && !emptiableParticle(baseSpecNode)) { reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::EmptyComplexRestrictionDerivation); } } // Delay particle constraint checking (5.3) until we have processed // the whole schema. } else { // Compose the final content model by concatenating the base and // the current in sequence if (!specNode) { specNodeWasNull = true; if (isMixed) { if (baseSpecNode && baseSpecNode->hasAllContent()) { reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::NotAllContent); throw TraverseSchema::InvalidComplexTypeInfo; // REVISIT - should we continue } } if (baseSpecNode) { specNodeJan.reset(new (fGrammarPoolMemoryManager) ContentSpecNode(*baseSpecNode)); specNode = specNodeJan.get(); typeInfo->setContentSpec(specNode); typeInfo->setAdoptContentSpec(true); specNodeJan.release(); } } else if (baseSpecNode) { if (specNode->hasAllContent() || baseSpecNode->hasAllContent()) { reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::NotAllContent); throw TraverseSchema::InvalidComplexTypeInfo; // REVISIT - should we continue } // Check for derivation valid (extension) - 1.4.3.2.2.1 if ((isMixed && baseContentType == SchemaElementDecl::Children) || (!isMixed && baseContentType != SchemaElementDecl::Children)) { reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::MixedOrElementOnly, baseLocalPart, typeName); throw TraverseSchema::InvalidComplexTypeInfo; //REVISIT - should we continue } typeInfo->setAdoptContentSpec(false); typeInfo->setContentSpec ( new (fGrammarPoolMemoryManager) ContentSpecNode ( ContentSpecNode::ModelGroupSequence , new (fGrammarPoolMemoryManager) ContentSpecNode(*baseSpecNode) , specNode , true , true , fGrammarPoolMemoryManager ) ); typeInfo->setAdoptContentSpec(true); } } } else { typeInfo->setDerivedBy(0); } // ------------------------------------------------------------- // Set the content type // ------------------------------------------------------------- if (isBaseAnyType && typeDerivedBy == SchemaSymbols::XSD_EXTENSION) { ContentSpecNode* anySpecNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( new (fGrammarPoolMemoryManager) QName ( XMLUni::fgZeroLenString , XMLUni::fgZeroLenString , fEmptyNamespaceURI, fGrammarPoolMemoryManager ) , false , fGrammarPoolMemoryManager ); anySpecNode->setType(ContentSpecNode::Any_Lax); anySpecNode->setMinOccurs(0); anySpecNode->setMaxOccurs(SchemaSymbols::XSD_UNBOUNDED); if (!specNode) { typeInfo->setContentSpec(anySpecNode); typeInfo->setDerivedBy(typeDerivedBy); } else { typeInfo->setAdoptContentSpec(false); typeInfo->setContentSpec ( new (fGrammarPoolMemoryManager) ContentSpecNode ( ContentSpecNode::ModelGroupSequence , anySpecNode , specNode , true , true , fGrammarPoolMemoryManager ) ); typeInfo->setAdoptContentSpec(true); if (!isMixed) { reportSchemaError(ctElem, XMLUni::fgXMLErrDomain, XMLErrs::MixedOrElementOnly, baseLocalPart, typeName); throw TraverseSchema::InvalidComplexTypeInfo; //REVISIT - should we continue } } typeInfo->setContentType(SchemaElementDecl::Mixed_Complex); } else if (isMixed) { if (specNode != 0) { typeInfo->setContentType(SchemaElementDecl::Mixed_Complex); } else { // add #PCDATA leaf and set its minOccurs to 0 ContentSpecNode* pcdataNode = new (fGrammarPoolMemoryManager) ContentSpecNode ( new (fGrammarPoolMemoryManager) QName ( XMLUni::fgZeroLenString , XMLUni::fgZeroLenString , XMLElementDecl::fgPCDataElemId , fGrammarPoolMemoryManager ) , false , fGrammarPoolMemoryManager ); pcdataNode->setMinOccurs(0); typeInfo->setContentSpec(pcdataNode); typeInfo->setAdoptContentSpec(true); typeInfo->setContentType(SchemaElementDecl::Mixed_Simple); } } else if (specNodeWasNull && (typeDerivedBy == SchemaSymbols::XSD_EXTENSION) && baseTypeInfo) { typeInfo->setBaseDatatypeValidator(baseTypeInfo->getBaseDatatypeValidator()); typeInfo->setDatatypeValidator(baseTypeInfo->getDatatypeValidator()); typeInfo->setContentType(baseTypeInfo->getContentType()); } else if (typeInfo->getContentSpec() == 0) { if (!effectiveContent_hasChild) { typeInfo->setContentType(SchemaElementDecl::Empty); } else { typeInfo->setContentType(SchemaElementDecl::ElementOnlyEmpty); } } else { typeInfo->setContentType(SchemaElementDecl::Children); } // ------------------------------------------------------------- // Now, check attributes and handle // ------------------------------------------------------------- if (attrNode != 0) { if (!isAttrOrAttrGroup(attrNode)) { reportSchemaError(attrNode, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType, attrNode->getLocalName()); } else { processAttributes(ctElem, attrNode, typeInfo, isBaseAnyType); } } else if (baseTypeInfo != 0 || isBaseAnyType) { processAttributes(ctElem, 0, typeInfo, isBaseAnyType); } } void TraverseSchema::processBaseTypeInfo(const DOMElement* const elem, const XMLCh* const baseName, const XMLCh* const localPart, const XMLCh* const uriStr, ComplexTypeInfo* const typeInfo) { SchemaInfo* saveInfo = fSchemaInfo; ComplexTypeInfo* baseComplexTypeInfo = 0; DatatypeValidator* baseDTValidator = 0; SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; unsigned int saveScope = fCurrentScope; // check if the base type is from another schema if (!XMLString::equals(uriStr, fTargetNSURIString)) { // check for datatype validator if it's schema for schema URI if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { baseDTValidator = getDatatypeValidator(uriStr, localPart); if (!baseDTValidator) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BaseTypeNotFound, baseName); throw TraverseSchema::InvalidComplexTypeInfo; } } else { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(uriStr); if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); throw TraverseSchema::InvalidComplexTypeInfo; } baseComplexTypeInfo = getTypeInfoFromNS(elem, uriStr, localPart); if (!baseComplexTypeInfo) { baseDTValidator = getDatatypeValidator(uriStr, localPart); if (!baseDTValidator) { SchemaInfo* impInfo = fSchemaInfo->getImportInfo(fURIStringPool->addOrFind(uriStr)); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BaseTypeNotFound, baseName); throw TraverseSchema::InvalidComplexTypeInfo; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } } } } else { fBuffer.set(uriStr); fBuffer.append(chComma); fBuffer.append(localPart); // assume the base is a complexType and try to locate the base type first const XMLCh* fullBaseName = fBuffer.getRawBuffer(); baseComplexTypeInfo = fComplexTypeRegistry->get(fullBaseName); // Circular check if (baseComplexTypeInfo) { if (fCurrentTypeNameStack->containsElement(fStringPool->addOrFind(fullBaseName), fCircularCheckIndex)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, fullBaseName); throw TraverseSchema::InvalidComplexTypeInfo; } else if (fCurrentTypeNameStack->containsElement(fStringPool->addOrFind(fullBaseName))) { typeInfo->setBaseComplexTypeInfo(baseComplexTypeInfo); throw TraverseSchema::RecursingElement; } else if (baseComplexTypeInfo->getPreprocessed()) { baseComplexTypeInfo = 0; } } } // if not found, 2 possibilities: // 1: ComplexType in question has not been compiled yet; // 2: base is SimpleType; if (!baseComplexTypeInfo && !baseDTValidator) { baseDTValidator = getDatatypeValidator(uriStr, localPart); if (baseDTValidator == 0) { DOMElement* baseTypeNode = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_ComplexType, SchemaSymbols::fgELT_COMPLEXTYPE, localPart, &fSchemaInfo); if (baseTypeNode != 0) { int baseTypeSymbol = traverseComplexTypeDecl(baseTypeNode); baseComplexTypeInfo = fComplexTypeRegistry->get(fStringPool->getValueForId(baseTypeSymbol)); } else { baseTypeNode = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_SimpleType, SchemaSymbols::fgELT_SIMPLETYPE, localPart, &fSchemaInfo); if (baseTypeNode != 0) { baseDTValidator = traverseSimpleTypeDecl(baseTypeNode); if (baseDTValidator == 0) { // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uriStr, localPart, uriStr); throw TraverseSchema::InvalidComplexTypeInfo; } } else { // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BaseTypeNotFound, baseName); throw TraverseSchema::InvalidComplexTypeInfo; } } } } // end if // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } typeInfo->setBaseComplexTypeInfo(baseComplexTypeInfo); typeInfo->setBaseDatatypeValidator(baseDTValidator); } ComplexTypeInfo* TraverseSchema::getTypeInfoFromNS(const DOMElement* const elem, const XMLCh* const uriStr, const XMLCh* const localPart) { Grammar* grammar = fGrammarResolver->getGrammar(uriStr); if (grammar != 0 && grammar->getGrammarType() == Grammar::SchemaGrammarType) { fBuffer.set(uriStr); fBuffer.append(chComma); fBuffer.append(localPart); ComplexTypeInfo* typeInfo = ((SchemaGrammar*)grammar)->getComplexTypeRegistry()->get(fBuffer.getRawBuffer()); return typeInfo; } else { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); } return 0; } void TraverseSchema::processAttributes(const DOMElement* const elem, const DOMElement* const attElem, ComplexTypeInfo* const typeInfo, const bool isBaseAnyType) { // If we do not have a complexTypeInfo, then what is the point of // processing. if (typeInfo == 0) { return; } ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo(); if (baseTypeInfo && baseTypeInfo->getPreprocessed()) throw TraverseSchema::RecursingElement; const DOMElement* child = attElem; SchemaAttDef* attWildCard = 0; Janitor janAttWildCard(0); XercesAttGroupInfo* attGroupInfo = 0; ValueVectorOf attGroupList(4, fGrammarPoolMemoryManager); for (; child != 0; child = XUtil::getNextSiblingElement(child)) { const XMLCh* childName = child->getLocalName(); if (XMLString::equals(childName, SchemaSymbols::fgELT_ATTRIBUTE)) { if(attWildCard) reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AnyAttributeBeforeAttribute); traverseAttributeDecl(child, typeInfo); } else if (XMLString::equals(childName, SchemaSymbols::fgELT_ATTRIBUTEGROUP)) { if(attWildCard) reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AnyAttributeBeforeAttribute); attGroupInfo = traverseAttributeGroupDecl(child, typeInfo); if (attGroupInfo && !attGroupList.containsElement(attGroupInfo)) { attGroupList.addElement(attGroupInfo); } } else if (XMLString::equals(childName, SchemaSymbols::fgELT_ANYATTRIBUTE) ) { if(attWildCard) reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAnyAttribute); attWildCard = traverseAnyAttribute(child); janAttWildCard.reset(attWildCard); } else { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInComplexType, childName); } } // ------------------------------------------------------------- // Handle wild card/any attribute // ------------------------------------------------------------- int derivedBy = typeInfo->getDerivedBy(); XMLSize_t attGroupListSize = attGroupList.size(); if (attGroupListSize) { SchemaAttDef* completeWildCard = 0; Janitor janCompleteWildCard(0); XMLAttDef::DefAttTypes defAttType = XMLAttDef::Default; bool defAttTypeSet = false; for (XMLSize_t i=0; i < attGroupListSize; i++) { attGroupInfo = attGroupList.elementAt(i); XMLSize_t anyAttCount = attGroupInfo->anyAttributeCount(); if (anyAttCount) { if (!defAttTypeSet) { defAttType = (attWildCard) ? attWildCard->getDefaultType() : attGroupInfo->anyAttributeAt(0)->getDefaultType(); defAttTypeSet = true; } SchemaAttDef* attGroupWildCard = attGroupInfo->getCompleteWildCard(); if (completeWildCard) { attWildCardIntersection(completeWildCard, attGroupWildCard); } else { completeWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(attGroupWildCard); janCompleteWildCard.reset(completeWildCard); } } } if (completeWildCard) { if (attWildCard) { attWildCardIntersection(attWildCard, completeWildCard); } else { attWildCard = completeWildCard; janCompleteWildCard.orphan(); janAttWildCard.reset(attWildCard); } attWildCard->setDefaultType(defAttType); } } SchemaAttDef* baseAttWildCard = (baseTypeInfo) ? baseTypeInfo->getAttWildCard() : 0; Janitor janBaseAttWildCard(0); if (derivedBy == SchemaSymbols::XSD_EXTENSION) { if (isBaseAnyType) { baseAttWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, fEmptyNamespaceURI, XMLAttDef::Any_Any, XMLAttDef::ProcessContents_Lax, fGrammarPoolMemoryManager); janBaseAttWildCard.reset(baseAttWildCard); } if (baseAttWildCard && attWildCard) { XMLAttDef::DefAttTypes saveDefType = attWildCard->getDefaultType(); attWildCardUnion(attWildCard, baseAttWildCard); attWildCard->setDefaultType(saveDefType); } } // ------------------------------------------------------------- // insert wildcard attribute // ------------------------------------------------------------- if (attWildCard) { typeInfo->setAttWildCard(attWildCard); janAttWildCard.orphan(); if (attWildCard->getType() == XMLAttDef::AttTypes_Unknown) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotExpressibleWildCardIntersection); } } else if (baseAttWildCard && derivedBy == SchemaSymbols::XSD_EXTENSION) { if (isBaseAnyType) { typeInfo->setAttWildCard(baseAttWildCard); janBaseAttWildCard.orphan(); } else { SchemaAttDef* newWildCard = new (fGrammarPoolMemoryManager) SchemaAttDef(baseAttWildCard); typeInfo->setAttWildCard(newWildCard); } } // ------------------------------------------------------------- // Check attributes derivation OK // ------------------------------------------------------------- bool baseWithAttributes = (baseTypeInfo && baseTypeInfo->hasAttDefs()); bool childWithAttributes = (typeInfo->hasAttDefs() || typeInfo->getAttWildCard()); if (derivedBy == SchemaSymbols::XSD_RESTRICTION && childWithAttributes) { if (!baseWithAttributes && !baseAttWildCard) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_1); } else { checkAttDerivationOK(elem, baseTypeInfo, typeInfo); } } // ------------------------------------------------------------- // merge in base type's attribute decls // ------------------------------------------------------------- if (baseTypeInfo && baseTypeInfo->hasAttDefs()) { SchemaAttDefList& baseAttList = (SchemaAttDefList&) baseTypeInfo->getAttDefList(); for (XMLSize_t i=0; igetLocalPart(); // if found a duplicate, then skip the one from the base type if (typeInfo->getAttDef(localPart, attName->getURI()) != 0) { if (derivedBy == SchemaSymbols::XSD_EXTENSION) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttInDerivation, localPart); } continue; } if (attDef.getDefaultType() != XMLAttDef::Prohibited) { SchemaAttDef* newAttDef = new (fGrammarPoolMemoryManager) SchemaAttDef(attName->getPrefix(), attName->getLocalPart(), attName->getURI(), attDef.getValue(), attDef.getType(), attDef.getDefaultType(), attDef.getEnumeration(), fGrammarPoolMemoryManager); newAttDef->setDatatypeValidator(attDef.getDatatypeValidator()); typeInfo->addAttDef(newAttDef); if (attDef.getBaseAttDecl()) newAttDef->setBaseAttDecl(attDef.getBaseAttDecl()); else newAttDef->setBaseAttDecl(&attDef); } } } } void TraverseSchema::defaultComplexTypeInfo(ComplexTypeInfo* const typeInfo) { if (typeInfo) { typeInfo->setDerivedBy(0); typeInfo->setContentType(SchemaElementDecl::Any); typeInfo->setDatatypeValidator(0); typeInfo->setContentSpec(0); typeInfo->setBaseComplexTypeInfo(0); typeInfo->setBaseDatatypeValidator(0); } } InputSource* TraverseSchema::resolveSchemaLocation(const XMLCh* const loc, const XMLResourceIdentifier::ResourceIdentifierType resourceIdentitiferType, const XMLCh* const nameSpace) { // ------------------------------------------------------------------ // Create an input source // ------------------------------------------------------------------ InputSource* srcToFill = 0; XMLCh* normalizedURI = 0; if (loc) { XMLString::removeChar(loc, 0xFFFF, fBuffer); normalizedURI = fBuffer.getRawBuffer(); } if (fEntityHandler){ XMLResourceIdentifier resourceIdentifier(resourceIdentitiferType, normalizedURI, nameSpace, 0, fSchemaInfo->getCurrentSchemaURL(), fLocator); srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier); } // If they didn't create a source via the entity resolver, then we // have to create one on our own if we have the schemaLocation (with // the update resolveEntity accepting nameSpace, a schemImport could // pass a null schemaLocation) if (!srcToFill && loc) { if (fScanner->getDisableDefaultEntityResolution()) return 0; XMLURL urlTmp(fMemoryManager); if ((!urlTmp.setURL(fSchemaInfo->getCurrentSchemaURL(), normalizedURI, urlTmp)) || (urlTmp.isRelative())) { if (!fScanner->getStandardUriConformant()) { XMLCh* tempURI = XMLString::replicate(normalizedURI, fMemoryManager); ArrayJanitor tempURIName(tempURI, fMemoryManager); XMLUri::normalizeURI(tempURI, fBuffer); srcToFill = new (fMemoryManager) LocalFileInputSource ( fSchemaInfo->getCurrentSchemaURL() , fBuffer.getRawBuffer() , fMemoryManager ); } else ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); } else { if (fScanner->getStandardUriConformant() && urlTmp.hasInvalidChar()) ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager); srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager); } } return srcToFill; } void TraverseSchema::restoreSchemaInfo(SchemaInfo* const toRestore, SchemaInfo::ListType const aListType, const unsigned int saveScope) { if (aListType == SchemaInfo::IMPORT) { // restore grammar info int targetNSURI = toRestore->getTargetNSURI(); fSchemaGrammar->setScopeCount (fScopeCount); fSchemaGrammar->setAnonTypeCount (fAnonXSTypeCount); fSchemaGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(toRestore->getTargetNSURIString()); fScopeCount = fSchemaGrammar->getScopeCount (); fAnonXSTypeCount = fSchemaGrammar->getAnonTypeCount (); fTargetNSURI = targetNSURI; fCurrentScope = saveScope; fDatatypeRegistry = fSchemaGrammar->getDatatypeRegistry(); fTargetNSURIString = fSchemaGrammar->getTargetNamespace(); fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry(); fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry(); fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry(); fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry(); fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups(); } fSchemaInfo = toRestore; } bool TraverseSchema::emptiableParticle(const ContentSpecNode* const specNode) { if (!fFullConstraintChecking || !specNode || (specNode->getMinTotalRange() == 0)) { return true; } return false; } void TraverseSchema::checkFixedFacet(const DOMElement* const elem, const XMLCh* const facetName, const DatatypeValidator* const baseDV, unsigned int& flags) { const XMLCh* fixedFacet = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED); if ((fixedFacet && *fixedFacet) && (XMLString::equals(fixedFacet, SchemaSymbols::fgATTVAL_TRUE) || XMLString::equals(fixedFacet, fgValueOne))) { if (XMLString::equals(SchemaSymbols::fgELT_LENGTH, facetName)) { flags |= DatatypeValidator::FACET_LENGTH; } if (XMLString::equals(SchemaSymbols::fgELT_MINLENGTH, facetName)) { flags |= DatatypeValidator::FACET_MINLENGTH; } else if (XMLString::equals(SchemaSymbols::fgELT_MAXLENGTH, facetName)) { flags |= DatatypeValidator::FACET_MAXLENGTH; } else if (XMLString::equals(SchemaSymbols::fgELT_MAXEXCLUSIVE, facetName)) { flags |= DatatypeValidator::FACET_MAXEXCLUSIVE; } else if (XMLString::equals(SchemaSymbols::fgELT_MAXINCLUSIVE, facetName)) { flags |= DatatypeValidator::FACET_MAXINCLUSIVE; } else if (XMLString::equals(SchemaSymbols::fgELT_MINEXCLUSIVE, facetName)) { flags |= DatatypeValidator::FACET_MINEXCLUSIVE; } else if (XMLString::equals(SchemaSymbols::fgELT_MININCLUSIVE, facetName)) { flags |= DatatypeValidator::FACET_MININCLUSIVE; } else if (XMLString::equals(SchemaSymbols::fgELT_TOTALDIGITS, facetName)) { flags |= DatatypeValidator::FACET_TOTALDIGITS; } else if (XMLString::equals(SchemaSymbols::fgELT_FRACTIONDIGITS, facetName)) { flags |= DatatypeValidator::FACET_FRACTIONDIGITS; } else if ((XMLString::equals(SchemaSymbols::fgELT_WHITESPACE, facetName)) && baseDV->getType() == DatatypeValidator::String) { flags |= DatatypeValidator::FACET_WHITESPACE; } } } void TraverseSchema::buildValidSubstitutionListB(const DOMElement* const elem, SchemaElementDecl* const elemDecl, SchemaElementDecl* const subsElemDecl) { SchemaElementDecl* chainElemDecl = subsElemDecl->getSubstitutionGroupElem(); while (chainElemDecl) { int chainElemURI = chainElemDecl->getURI(); XMLCh* chainElemName = chainElemDecl->getBaseName(); ValueVectorOf* validSubsElements = fValidSubstitutionGroups->get(chainElemName, chainElemURI); if (!validSubsElements) { if (fTargetNSURI == chainElemURI) { break; // an error must have occured } SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(fURIStringPool->getValueForId(chainElemURI)); if (!aGrammar) break; validSubsElements = aGrammar->getValidSubstitutionGroups()->get(chainElemName, chainElemURI); if (!validSubsElements) { break; } validSubsElements = new (fGrammarPoolMemoryManager) ValueVectorOf(*validSubsElements); fValidSubstitutionGroups->put((void*) chainElemName, chainElemURI, validSubsElements); } if (validSubsElements->containsElement(elemDecl) || !isSubstitutionGroupValid(elem, chainElemDecl, elemDecl->getComplexTypeInfo(), elemDecl->getDatatypeValidator(), 0, false)) { break; } validSubsElements->addElement(elemDecl); // update related subs. info in case of circular import BaseRefVectorEnumerator importingEnum = fSchemaInfo->getImportingListEnumerator(); while (importingEnum.hasMoreElements()) { const SchemaInfo& curRef = importingEnum.nextElement(); SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(curRef.getTargetNSURIString()); ValueVectorOf* subsElemList = aGrammar->getValidSubstitutionGroups()->get(chainElemName, chainElemURI); if (subsElemList && !subsElemList->containsElement(elemDecl)) { subsElemList->addElement(elemDecl); } } chainElemDecl = chainElemDecl->getSubstitutionGroupElem(); } } void TraverseSchema::buildValidSubstitutionListF(const DOMElement* const elem, SchemaElementDecl* const elemDecl, SchemaElementDecl* const subsElemDecl) { int elemURI = elemDecl->getURI(); XMLCh* elemName = elemDecl->getBaseName(); ValueVectorOf* validSubsElements =fValidSubstitutionGroups->get(elemName, elemURI); if (validSubsElements) { int subsElemURI = subsElemDecl->getURI(); XMLCh* subsElemName = subsElemDecl->getBaseName(); ValueVectorOf* validSubs = fValidSubstitutionGroups->get(subsElemName, subsElemURI); if (!validSubs) { if (fTargetNSURI == subsElemURI) { return; // an error must have occured } SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(fURIStringPool->getValueForId(subsElemURI)); if (!aGrammar) return; validSubs = aGrammar->getValidSubstitutionGroups()->get(subsElemName, subsElemURI); if (!validSubs) { return; } validSubs = new (fGrammarPoolMemoryManager) ValueVectorOf(*validSubs); fValidSubstitutionGroups->put((void*) subsElemName, subsElemURI, validSubs); } XMLSize_t elemSize = validSubsElements->size(); for (XMLSize_t i=0; ielementAt(i); if (validSubs->containsElement(chainElem)) { continue; } if (isSubstitutionGroupValid(elem, subsElemDecl, chainElem->getComplexTypeInfo(), chainElem->getDatatypeValidator(), 0, false)) { validSubs->addElement(chainElem); buildValidSubstitutionListB(elem, chainElem, subsElemDecl); } } } } void TraverseSchema::checkEnumerationRequiredNotation(const DOMElement* const elem, const XMLCh* const name, const XMLCh* const type) { const XMLCh* localPart = getLocalPart(type); if (XMLString::equals(localPart, XMLUni::fgNotationString)) { const XMLCh* prefix = getPrefix(type); const XMLCh* typeURI = resolvePrefixToURI(elem, prefix); if (XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNotationType, name); } } } XercesGroupInfo* TraverseSchema::processGroupRef(const DOMElement* const elem, const XMLCh* const refName) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true); Janitor janAnnot(fAnnotation); if (content != 0) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::NoContentForRef, SchemaSymbols::fgELT_GROUP); } const XMLCh* prefix = getPrefix(refName); const XMLCh* localPart = getLocalPart(refName); const XMLCh* uriStr = resolvePrefixToURI(elem, prefix); fBuffer.set(uriStr); fBuffer.append(chComma); fBuffer.append(localPart); unsigned int nameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer()); if (fCurrentGroupStack->containsElement(nameIndex)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, localPart); return 0; } XercesGroupInfo* groupInfo = 0; SchemaInfo* saveInfo = fSchemaInfo; SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; unsigned int saveScope = fCurrentScope; //if from another target namespace if (!XMLString::equals(uriStr, fTargetNSURIString)) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(uriStr); if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); return 0; } Grammar* aGrammar = fGrammarResolver->getGrammar(uriStr); if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr); return 0; } groupInfo = ((SchemaGrammar*)aGrammar)->getGroupInfoRegistry()->get(fStringPool->getValueForId(nameIndex)); if (!groupInfo) { SchemaInfo* impInfo = fSchemaInfo->getImportInfo(fURIStringPool->addOrFind(uriStr)); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, SchemaSymbols::fgELT_GROUP, uriStr, localPart); return 0; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } } else { groupInfo = fGroupRegistry->get(fStringPool->getValueForId(nameIndex)); } if (!groupInfo) { DOMElement* groupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Group, SchemaSymbols::fgELT_GROUP, localPart, &fSchemaInfo); if (groupElem != 0) { groupInfo = traverseGroupDecl(groupElem); // restore schema information restoreSchemaInfo(saveInfo, infoType, saveScope); if (groupInfo && (fCurrentGroupInfo || infoType == SchemaInfo::IMPORT)) { copyGroupElements(elem, groupInfo, fCurrentGroupInfo, (infoType == SchemaInfo::IMPORT) ? fCurrentComplexType : 0); } return groupInfo; } else { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, SchemaSymbols::fgELT_GROUP, uriStr, localPart); } // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } } else { copyGroupElements(elem, groupInfo, fCurrentGroupInfo, fCurrentComplexType); } return groupInfo; } XercesAttGroupInfo* TraverseSchema::processAttributeGroupRef(const DOMElement* const elem, const XMLCh* const refName, ComplexTypeInfo* const typeInfo) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) { reportSchemaError(elem ,XMLUni::fgValidityDomain, XMLValid::NoContentForRef, SchemaSymbols::fgELT_ATTRIBUTEGROUP); } Janitor janAnnot(fAnnotation); const XMLCh* prefix = getPrefix(refName); const XMLCh* localPart = getLocalPart(refName); const XMLCh* uriStr = resolvePrefixToURI(elem, prefix); XercesAttGroupInfo* attGroupInfo = 0; SchemaInfo* saveInfo = fSchemaInfo; SchemaInfo::ListType infoType = SchemaInfo::INCLUDE; unsigned int saveScope = fCurrentScope; if (!XMLString::equals(uriStr, fTargetNSURIString)) { // Make sure that we have an explicit import statement. // Clause 4 of Schema Representation Constraint: // http://www.w3.org/TR/xmlschema-1/#src-resolve unsigned int uriId = fURIStringPool->addOrFind(uriStr); if (!isImportingNS(uriId)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidNSReference, uriStr); return 0; } attGroupInfo = traverseAttributeGroupDeclNS(elem, uriStr, localPart); if (!attGroupInfo) { SchemaInfo* impInfo = fSchemaInfo->getImportInfo(fURIStringPool->addOrFind(uriStr)); if (!impInfo || impInfo->getProcessed()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, SchemaSymbols::fgELT_ATTRIBUTEGROUP, uriStr, localPart); return 0; } infoType = SchemaInfo::IMPORT; restoreSchemaInfo(impInfo, infoType); } } else { attGroupInfo = fAttGroupRegistry->get(localPart); } if (!attGroupInfo) { // traverse top level attributeGroup - if found DOMElement* attGroupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_AttributeGroup, SchemaSymbols::fgELT_ATTRIBUTEGROUP, localPart, &fSchemaInfo); if (attGroupElem != 0) { // circular attribute check if (fDeclStack->containsElement(attGroupElem)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, refName); return 0; } attGroupInfo = traverseAttributeGroupDecl(attGroupElem, typeInfo, true); if (attGroupInfo && fCurrentAttGroupInfo) { copyAttGroupAttributes(elem, attGroupInfo, fCurrentAttGroupInfo, 0); } // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType, saveScope); } return attGroupInfo; } else { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound, SchemaSymbols::fgELT_ATTRIBUTEGROUP, uriStr, localPart); } } if (attGroupInfo) { copyAttGroupAttributes(elem, attGroupInfo, fCurrentAttGroupInfo, typeInfo); } // restore schema information, if necessary if (saveInfo != fSchemaInfo) { restoreSchemaInfo(saveInfo, infoType); } return attGroupInfo; } void TraverseSchema::processElements(const DOMElement* const elem, ComplexTypeInfo* const baseTypeInfo, ComplexTypeInfo* const newTypeInfo) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); XMLSize_t elemCount = baseTypeInfo->elementCount(); if (elemCount) { int newTypeScope = newTypeInfo->getScopeDefined(); int schemaURI = fURIStringPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); for (XMLSize_t i=0; i < elemCount; i++) { SchemaGrammar* aGrammar = fSchemaGrammar; SchemaElementDecl* elemDecl = baseTypeInfo->elementAt(i); int elemURI = elemDecl->getURI(); unsigned int elemScope = elemDecl->getEnclosingScope(); if (elemScope != Grammar::TOP_LEVEL_SCOPE) { if (elemURI != fTargetNSURI && elemURI != schemaURI && elemURI != fEmptyNamespaceURI) { Grammar* aGrammar = fGrammarResolver->getGrammar(fURIStringPool->getValueForId(elemURI)); if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) { continue; // REVISIT - error message } } const XMLCh* localPart = elemDecl->getBaseName(); const SchemaElementDecl* other = (SchemaElementDecl*) aGrammar->getElemDecl(elemURI, localPart, 0, newTypeScope); if (other) { if (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() || elemDecl->getDatatypeValidator() != other->getDatatypeValidator()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, localPart); } continue; } elemDecl->setEnclosingScope(newTypeScope); ((SchemaGrammar*) aGrammar)->putGroupElemDecl(elemDecl); elemDecl->setEnclosingScope(elemScope); } newTypeInfo->addElement(elemDecl); } } } void TraverseSchema::processElements(const DOMElement* const elem, XercesGroupInfo* const fromGroup, ComplexTypeInfo* const typeInfo) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); XMLSize_t elemCount = fromGroup->elementCount(); int newScope = typeInfo->getScopeDefined(); for (XMLSize_t i = 0; i < elemCount; i++) { SchemaElementDecl* elemDecl = fromGroup->elementAt(i); unsigned int elemScope = elemDecl->getEnclosingScope(); if (elemScope != Grammar::TOP_LEVEL_SCOPE) { int elemURI = elemDecl->getURI(); const XMLCh* localPart = elemDecl->getBaseName(); const SchemaElementDecl* other = (SchemaElementDecl*) fSchemaGrammar->getElemDecl(elemURI, localPart, 0, newScope); if (other) { if (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() || elemDecl->getDatatypeValidator() != other->getDatatypeValidator()) { reportSchemaError( elem, XMLUni::fgXMLErrDomain , XMLErrs::DuplicateElementDeclaration, localPart); } continue; } elemDecl->setEnclosingScope(newScope); fSchemaGrammar->putGroupElemDecl(elemDecl); elemDecl->setEnclosingScope(elemScope); typeInfo->addElement(elemDecl); } } } void TraverseSchema::copyGroupElements(const DOMElement* const elem, XercesGroupInfo* const fromGroup, XercesGroupInfo* const toGroup, ComplexTypeInfo* const typeInfo) { XMLSize_t elemCount = fromGroup->elementCount(); int newScope = (typeInfo) ? typeInfo->getScopeDefined() : 0; if (typeInfo) fromGroup->setCheckElementConsistency(false); for (XMLSize_t i = 0; i < elemCount; i++) { SchemaElementDecl* elemDecl = fromGroup->elementAt(i); if (typeInfo) { unsigned int elemScope = elemDecl->getEnclosingScope(); if (elemScope != Grammar::TOP_LEVEL_SCOPE) { int elemURI = elemDecl->getURI(); const XMLCh* localPart = elemDecl->getBaseName(); const SchemaElementDecl* other = (SchemaElementDecl*) fSchemaGrammar->getElemDecl(elemURI, localPart, 0, newScope); if (other) { if (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() || elemDecl->getDatatypeValidator() != other->getDatatypeValidator()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, localPart); } continue; } elemDecl->setEnclosingScope(newScope); fSchemaGrammar->putGroupElemDecl(elemDecl); elemDecl->setEnclosingScope(elemScope); } typeInfo->addElement(elemDecl); } if (toGroup) { toGroup->addElement(elemDecl); } } } void TraverseSchema::copyAttGroupAttributes(const DOMElement* const elem, XercesAttGroupInfo* const fromAttGroup, XercesAttGroupInfo* const toAttGroup, ComplexTypeInfo* const typeInfo) { XMLSize_t attCount = fromAttGroup->attributeCount(); for (XMLSize_t i=0; i < attCount; i++) { SchemaAttDef* attDef = fromAttGroup->attributeAt(i); QName* attName = attDef->getAttName(); const XMLCh* localPart = attName->getLocalPart(); DatatypeValidator* attDV = attDef->getDatatypeValidator(); if (typeInfo) { if (typeInfo->getAttDef(localPart, attName->getURI())) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, localPart); continue; } if (attDV && attDV->getType() == DatatypeValidator::ID) { if (typeInfo->containsAttWithTypeId()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, localPart); continue; } typeInfo->setAttWithTypeId(true); } SchemaAttDef* clonedAttDef = new (fGrammarPoolMemoryManager) SchemaAttDef(attDef); typeInfo->addAttDef(clonedAttDef); if (!clonedAttDef->getBaseAttDecl()) clonedAttDef->setBaseAttDecl(attDef); if (toAttGroup) { toAttGroup->addAttDef(attDef, true); } } else { if (toAttGroup->containsAttribute(localPart, attName->getURI())) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, localPart); continue; } if (attDV && attDV->getType() == DatatypeValidator::ID) { if (toAttGroup->containsTypeWithId()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, localPart); continue; } toAttGroup->setTypeWithId(true); } toAttGroup->addAttDef(attDef, true); } } if (toAttGroup) { XMLSize_t anyAttCount = fromAttGroup->anyAttributeCount(); for (XMLSize_t j=0; j < anyAttCount; j++) { toAttGroup->addAnyAttDef(fromAttGroup->anyAttributeAt(j), true); } } } void TraverseSchema::attWildCardIntersection(SchemaAttDef* const resultWildCard, const SchemaAttDef* const compareWildCard) { XMLAttDef::AttTypes typeR = resultWildCard->getType(); XMLAttDef::AttTypes typeC = compareWildCard->getType(); //If either O1 or O2 is any, then the other must be the value. if (typeC == XMLAttDef::Any_Any || typeR == XMLAttDef::AttTypes_Unknown) { return; } if (typeR == XMLAttDef::Any_Any || typeC == XMLAttDef::AttTypes_Unknown) { resultWildCard->resetNamespaceList(); copyWildCardData(compareWildCard, resultWildCard); return; } // If either O1 or O2 is a pair of not and a namespace name and the other // is a set, then that set, minus the negated namespace name if it was in // is the value if ((typeC == XMLAttDef::Any_Other && typeR == XMLAttDef::Any_List) || (typeR == XMLAttDef::Any_Other && typeC == XMLAttDef::Any_List)) { unsigned int compareURI = 0; ValueVectorOf* nameURIList = 0; if (typeC == XMLAttDef::Any_List) { nameURIList = compareWildCard->getNamespaceList(); compareURI = resultWildCard->getAttName()->getURI(); } else { nameURIList = resultWildCard->getNamespaceList(); compareURI = compareWildCard->getAttName()->getURI(); } XMLSize_t listSize = (nameURIList) ? nameURIList->size() : 0; if (listSize) { bool found = false; ValueVectorOf tmpURIList(listSize, fGrammarPoolMemoryManager); for (XMLSize_t i=0; i < listSize; i++) { unsigned int nameURI = nameURIList->elementAt(i); if (nameURI != compareURI && nameURI != (unsigned int) fEmptyNamespaceURI) { tmpURIList.addElement(nameURI); } else { found = true; } } if (found || typeC == XMLAttDef::Any_List) { resultWildCard->setNamespaceList(&tmpURIList); } } if (typeC == XMLAttDef::Any_List) { copyWildCardData(compareWildCard, resultWildCard); } return; } // If both O1 and O2 are sets, then the intersection of those sets must be // the value. if (typeR == XMLAttDef::Any_List && typeC == XMLAttDef::Any_List) { ValueVectorOf* uriListR = resultWildCard->getNamespaceList(); ValueVectorOf* uriListC = compareWildCard->getNamespaceList(); XMLSize_t listSize = (uriListC) ? uriListC->size() : 0; if (listSize) { ValueVectorOf tmpURIList(listSize, fGrammarPoolMemoryManager); for (XMLSize_t i=0; i < listSize; i++) { unsigned int uriName = uriListC->elementAt(i); if (uriListR && uriListR->containsElement(uriName)) { tmpURIList.addElement(uriName); } } resultWildCard->setNamespaceList(&tmpURIList); } else { resultWildCard->resetNamespaceList(); } return; } // If the two are negations of different namespace names, then: // if one is a negation of absent, then result is negation of namespace // else intersection is not expressible. if (typeR == XMLAttDef::Any_Other && typeC == XMLAttDef::Any_Other) { QName* qnameR = resultWildCard->getAttName(); if (qnameR->getURI() != compareWildCard->getAttName()->getURI()) { if (qnameR->getURI() == (unsigned int)fEmptyNamespaceURI) { qnameR->setURI(compareWildCard->getAttName()->getURI()); } else if (compareWildCard->getAttName()->getURI() != (unsigned int)fEmptyNamespaceURI) { qnameR->setURI(fEmptyNamespaceURI); resultWildCard->setType(XMLAttDef::AttTypes_Unknown); } } } } void TraverseSchema::attWildCardUnion(SchemaAttDef* const resultWildCard, const SchemaAttDef* const compareWildCard) { XMLAttDef::AttTypes typeR = resultWildCard->getType(); XMLAttDef::AttTypes typeC = compareWildCard->getType(); //If either O1 or O2 is any, then the other must be the value. if (typeR == XMLAttDef::Any_Any || typeR == XMLAttDef::AttTypes_Unknown) { return; } if (typeC == XMLAttDef::Any_Any || typeC == XMLAttDef::AttTypes_Unknown) { resultWildCard->resetNamespaceList(); copyWildCardData(compareWildCard, resultWildCard); return; } // If both O1 and O2 are sets, then the union of those sets must be // the value. if (typeR == XMLAttDef::Any_List && typeC == XMLAttDef::Any_List) { ValueVectorOf* uriListR = resultWildCard->getNamespaceList(); ValueVectorOf* uriListC = compareWildCard->getNamespaceList(); XMLSize_t listSizeC = (uriListC) ? uriListC->size() : 0; if (listSizeC) { if (!uriListR || !uriListR->size()) { resultWildCard->setNamespaceList(uriListC); return; } ValueVectorOf tmpURIList(*uriListR); for (XMLSize_t i = 0; i < listSizeC; i++) { unsigned int uriName = uriListC->elementAt(i); if (!uriListR->containsElement(uriName)) { tmpURIList.addElement(uriName); } } resultWildCard->setNamespaceList(&tmpURIList); } return; } // If the two are negations of different namespace names, then not and // absent must be the value if (typeR == XMLAttDef::Any_Other && typeC == XMLAttDef::Any_Other) { QName* qnameR = resultWildCard->getAttName(); if (qnameR->getURI() != compareWildCard->getAttName()->getURI()) { qnameR->setURI(fEmptyNamespaceURI); resultWildCard->setType(XMLAttDef::Any_Other); } } // 5. If either O1 or O2 is a pair of not and a namespace name and the // other is a set, then: // 1. If the set includes both the negated namespace name and absent // then any must be the value. // 2. If the set includes the negated namespace name but not absent, // then a pair of not and absent must be the value. // 3. If the set includes absent but not the negated namespace name, // then the union is not expressible. // 4. If the set does not include either the negated namespace or // absent, then whichever of O1 or O2 is a pair of not and a // namespace name. // // 6. If either O1 or O2 is a pair of not and absent and the other is a // set, then: // 1. If the set includes absent then any must be the value. // 2. If the set does not include absent, then a pair of not and // absent. if ((typeC == XMLAttDef::Any_Other && typeR == XMLAttDef::Any_List) || (typeR == XMLAttDef::Any_Other && typeC == XMLAttDef::Any_List)) { ValueVectorOf* nameURIList = 0; QName* attNameR = resultWildCard->getAttName(); unsigned int compareURI = 0; if (typeC == XMLAttDef::Any_List) { nameURIList = compareWildCard->getNamespaceList(); compareURI = attNameR->getURI(); } else { nameURIList = resultWildCard->getNamespaceList(); compareURI = compareWildCard->getAttName()->getURI(); } // 6. not and absent if (compareURI == (unsigned int) fEmptyNamespaceURI) { if (nameURIList) { // 6.1 result is any if (nameURIList->containsElement(compareURI)) { resultWildCard->setType(XMLAttDef::Any_Any); attNameR->setURI(fEmptyNamespaceURI); } // 6.2 result is not and absent else if (typeR == XMLAttDef::Any_List){ resultWildCard->setType(XMLAttDef::Any_Other); attNameR->setURI(fEmptyNamespaceURI); } } // 6.2 result is not and absent else if (typeR == XMLAttDef::Any_List) { resultWildCard->setType(XMLAttDef::Any_Other); attNameR->setURI(fEmptyNamespaceURI); } } // 5. not and namespace else { // 5.3 result is not expressible if (!nameURIList) { resultWildCard->setType(XMLAttDef::AttTypes_Unknown); attNameR->setURI(fEmptyNamespaceURI); } else { bool containsAbsent = nameURIList->containsElement(fEmptyNamespaceURI); bool containsNamespace = nameURIList->containsElement(compareURI); // 5.1 result is any if (containsAbsent && containsNamespace) { resultWildCard->setType(XMLAttDef::Any_Any); attNameR->setURI(fEmptyNamespaceURI); } // 5.2 result is not and absent else if (containsNamespace) { resultWildCard->setType(XMLAttDef::Any_Other); attNameR->setURI(fEmptyNamespaceURI); } // 5.3 result is not expressible else if (containsAbsent) { resultWildCard->setType(XMLAttDef::AttTypes_Unknown); attNameR->setURI(fEmptyNamespaceURI); } // 5.4. whichever is not and namespace else if (typeR == XMLAttDef::Any_List) { resultWildCard->setType(XMLAttDef::Any_Other); attNameR->setURI(compareURI); } } } resultWildCard->resetNamespaceList(); } } void TraverseSchema::checkAttDerivationOK(const DOMElement* const elem, const ComplexTypeInfo* const baseTypeInfo, const ComplexTypeInfo* const childTypeInfo) { SchemaAttDefList& childAttList = (SchemaAttDefList&) childTypeInfo->getAttDefList(); const SchemaAttDef* baseAttWildCard = baseTypeInfo->getAttWildCard(); for (XMLSize_t i=0; igetLocalPart(); const SchemaAttDef* baseAttDef = baseTypeInfo->getAttDef(childLocalPart, childAttName->getURI()); if (baseAttDef) { XMLAttDef::DefAttTypes baseAttDefType = baseAttDef->getDefaultType(); XMLAttDef::DefAttTypes childAttDefType = childAttDef.getDefaultType(); // Constraint 2.1.1 & 3 + check for prohibited base attribute if (baseAttDefType == XMLAttDef::Prohibited && childAttDefType != XMLAttDef::Prohibited) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_8, childLocalPart); } if ((baseAttDefType & XMLAttDef::Required) && !(childAttDefType & XMLAttDef::Required)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_2, childLocalPart); } // if the attribute in the derived type is prohibited, and it didn't try to override a required attribute, // it's ok and shouldn't be tested for data type or fixed value if (childAttDefType == XMLAttDef::Prohibited) continue; // Constraint 2.1.2 DatatypeValidator* baseDV = baseAttDef->getDatatypeValidator(); DatatypeValidator* childDV = childAttDef.getDatatypeValidator(); if (!baseDV || !baseDV->isSubstitutableBy(childDV)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_3, childLocalPart); } // Constraint 2.1.3 if ((baseAttDefType & XMLAttDef::Fixed) && (!(childAttDefType & XMLAttDef::Fixed) || !XMLString::equals(baseAttDef->getValue(), childAttDef.getValue()))) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_4, childLocalPart); } } // Constraint 2.2 else if (!baseAttWildCard || !wildcardAllowsNamespace(baseAttWildCard, childAttName->getURI())) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_5, childLocalPart); } } // Constraint 4 const SchemaAttDef* childAttWildCard = childTypeInfo->getAttWildCard(); if (childAttWildCard) { if (!baseAttWildCard) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_6); } else if (!isWildCardSubset(baseAttWildCard, childAttWildCard)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_7); } else if (childAttWildCard->getDefaultType() < baseAttWildCard->getDefaultType()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_9); } } } void TraverseSchema::checkAttDerivationOK(const DOMElement* const elem, const XercesAttGroupInfo* const baseAttGrpInfo, const XercesAttGroupInfo* const childAttGrpInfo) { XMLSize_t baseAttCount = baseAttGrpInfo->attributeCount(); XMLSize_t baseAnyAttCount = baseAttGrpInfo->anyAttributeCount(); XMLSize_t childAttCount = childAttGrpInfo->attributeCount(); XMLSize_t childAnyAttCount = childAttGrpInfo->anyAttributeCount(); if ((childAttCount || childAnyAttCount) && (!baseAttCount && !baseAnyAttCount)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_1); } const SchemaAttDef* baseAttWildCard = (baseAnyAttCount) ? baseAttGrpInfo->anyAttributeAt(0) : 0; for (XMLSize_t i=0; iattributeAt(i); QName* childAttName = childAttDef->getAttName(); const XMLCh* childLocalPart = childAttName->getLocalPart(); const SchemaAttDef* baseAttDef = baseAttGrpInfo->getAttDef(childLocalPart, childAttName->getURI()); if (baseAttDef) { XMLAttDef::DefAttTypes baseAttDefType = baseAttDef->getDefaultType(); XMLAttDef::DefAttTypes childAttDefType = childAttDef->getDefaultType(); // Constraint 2.1.1 & 3 + check for prohibited base attribute if (baseAttDefType == XMLAttDef::Prohibited && childAttDefType != XMLAttDef::Prohibited) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_8, childLocalPart); } if ((baseAttDefType & XMLAttDef::Required) && !(childAttDefType & XMLAttDef::Required)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_2, childLocalPart); } // if the attribute in the derived type is prohibited, and it didn't try to override a required attribute, // it's ok and shouldn't be tested for data type or fixed value if (childAttDefType == XMLAttDef::Prohibited) continue; // Constraint 2.1.2 DatatypeValidator* baseDV = baseAttDef->getDatatypeValidator(); DatatypeValidator* childDV = childAttDef->getDatatypeValidator(); if (!baseDV || !baseDV->isSubstitutableBy(childDV)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_3, childLocalPart); } // Constraint 2.1.3 if ((baseAttDefType & XMLAttDef::Fixed) && (!(childAttDefType & XMLAttDef::Fixed) || !XMLString::equals(baseAttDef->getValue(), childAttDef->getValue()))) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_4, childLocalPart); } } // Constraint 2.2 else if (!baseAttWildCard || !wildcardAllowsNamespace(baseAttWildCard, childAttName->getURI())) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_5, childLocalPart); } } // Constraint 4 const SchemaAttDef* childAttWildCard = (childAnyAttCount) ? childAttGrpInfo->anyAttributeAt(0) : 0; if (childAttWildCard) { if (!baseAttWildCard) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_6); } else if (!isWildCardSubset(baseAttWildCard, childAttWildCard)) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_7); } else if (childAttWildCard->getDefaultType() < baseAttWildCard->getDefaultType()) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttDerivation_9); } } } bool TraverseSchema::wildcardAllowsNamespace(const SchemaAttDef* const wildCard, const unsigned int nameURI) { XMLAttDef::AttTypes wildCardType = wildCard->getType(); // The constraint must be any if (wildCardType == XMLAttDef::Any_Any) { return true; } // All of the following must be true: // 2.1 The constraint is a pair of not and a namespace name or absent // 2.2 The value must not be identical to the namespace test. // 2.3 The value must not be absent. if (wildCardType == XMLAttDef::Any_Other && ((int) nameURI) != fEmptyNamespaceURI && wildCard->getAttName()->getURI() != nameURI) { return true; } // The constraint is a set, and the value is identical to one of the // members of the set if (wildCardType == XMLAttDef::Any_List) { ValueVectorOf* nameURIList = wildCard->getNamespaceList(); if (nameURIList->containsElement(nameURI)) { return true; } } return false; } bool TraverseSchema::isWildCardSubset(const SchemaAttDef* const baseAttWildCard, const SchemaAttDef* const childAttWildCard) { XMLAttDef::AttTypes baseWildCardType = baseAttWildCard->getType(); XMLAttDef::AttTypes childWildCardType = childAttWildCard->getType(); if (baseWildCardType == XMLAttDef::AttTypes_Unknown || childWildCardType == XMLAttDef::AttTypes_Unknown) { return false; } // 1 super must be any. if (baseWildCardType == XMLAttDef::Any_Any) { return true; } // 2 All of the following must be true: // 2.1 sub must be a pair of not and a namespace name or absent. // 2.2 super must be a pair of not and the same value. if (childWildCardType == XMLAttDef::Any_Other && baseWildCardType == XMLAttDef::Any_Other && childAttWildCard->getAttName()->getURI() == baseAttWildCard->getAttName()->getURI()) { return true; } // 3 All of the following must be true: // 3.1 sub must be a set whose members are either namespace names or absent. // 3.2 One of the following must be true: // 3.2.1 super must be the same set or a superset thereof. // 3.2.2 super must be a pair of not and a namespace name or absent and // that value must not be in sub's set. if (childWildCardType == XMLAttDef::Any_List) { ValueVectorOf* childURIList = childAttWildCard->getNamespaceList(); if (baseWildCardType == XMLAttDef::Any_List) { ValueVectorOf* baseURIList = baseAttWildCard->getNamespaceList(); XMLSize_t childListSize = (childURIList) ? childURIList->size() : 0; for (XMLSize_t i=0; icontainsElement(childURIList->elementAt(i))) { return false; } } return true; } else if (baseWildCardType == XMLAttDef::Any_Other) { if (!childURIList->containsElement(baseAttWildCard->getAttName()->getURI())) { return true; } } } return false; } bool TraverseSchema::openRedefinedSchema(const DOMElement* const redefineElem) { if (fPreprocessedNodes->containsKey(redefineElem)) { restoreSchemaInfo(fPreprocessedNodes->get(redefineElem)); return true; } // ------------------------------------------------------------------ // Get 'schemaLocation' attribute // ------------------------------------------------------------------ const XMLCh* schemaLocation = getElementAttValue(redefineElem, SchemaSymbols::fgATT_SCHEMALOCATION, DatatypeValidator::AnyURI); if (!schemaLocation || !*schemaLocation) { reportSchemaError(redefineElem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNoSchemaLocation, SchemaSymbols::fgELT_REDEFINE); return false; } // ------------------------------------------------------------------ // Resolve schema location // ------------------------------------------------------------------ fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, ((XSDElementNSImpl*) redefineElem)->getLineNo(), ((XSDElementNSImpl*) redefineElem)->getColumnNo()); InputSource* srcToFill = resolveSchemaLocation(schemaLocation, XMLResourceIdentifier::SchemaRedefine); Janitor janSrc(srcToFill); // Nothing to do if (!srcToFill) { return false; } const XMLCh* includeURL = srcToFill->getSystemId(); if (XMLString::equals(includeURL, fSchemaInfo->getCurrentSchemaURL())) { return false; } SchemaInfo* redefSchemaInfo = fCachedSchemaInfoList->get(includeURL, fTargetNSURI); if (!redefSchemaInfo && fSchemaInfoList != fCachedSchemaInfoList) redefSchemaInfo = fSchemaInfoList->get(includeURL, fTargetNSURI); if (redefSchemaInfo) { reportSchemaError(redefineElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidRedefine, includeURL); return false; } // ------------------------------------------------------------------ // Parse input source // ------------------------------------------------------------------ if (!fParser) fParser = new (fGrammarPoolMemoryManager) XSDDOMParser(0,fGrammarPoolMemoryManager, 0); fParser->setValidationScheme(XercesDOMParser::Val_Never); fParser->setDoNamespaces(true); fParser->setUserEntityHandler(fEntityHandler); fParser->setUserErrorReporter(fErrorReporter); // Should just issue warning if the schema is not found bool flag = srcToFill->getIssueFatalErrorIfNotFound(); srcToFill->setIssueFatalErrorIfNotFound(false); fParser->parse(*srcToFill) ; // Reset the InputSource srcToFill->setIssueFatalErrorIfNotFound(flag); if (fParser->getSawFatal() && fScanner->getExitOnFirstFatal()) reportSchemaError(redefineElem, XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError); // ------------------------------------------------------------------ // Get root element // ------------------------------------------------------------------ DOMDocument* document = fParser->getDocument(); if (!document) { return false; } else { DOMElement* root = document->getDocumentElement(); if (root == 0) { return false; } const XMLCh* targetNSURIString = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE); // check to see if targetNameSpace is right if (*targetNSURIString && !XMLString::equals(targetNSURIString,fTargetNSURIString)){ reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::RedefineNamespaceDifference, schemaLocation, targetNSURIString); return false; } // if targetNamespace is empty, change it to redefin'g schema // targetNamespace if (!*targetNSURIString && root->getAttributeNode(XMLUni::fgXMLNSString) == 0 && fTargetNSURI != fEmptyNamespaceURI) { root->setAttribute(XMLUni::fgXMLNSString, fTargetNSURIString); } // -------------------------------------------------------- // Update schema information with redefined schema // -------------------------------------------------------- redefSchemaInfo = fSchemaInfo; Janitor newSchemaInfo(new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI, 0, includeURL, fTargetNSURIString, root, fScanner, fGrammarPoolMemoryManager)); fSchemaInfo = newSchemaInfo.get(); fSchemaInfo->getNamespaceScope()->reset(fEmptyNamespaceURI); // Add mapping for the xml prefix fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgXMLString, fURIStringPool->addOrFind(XMLUni::fgXMLURIName)); traverseSchemaHeader(root); fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), fSchemaInfo->getTargetNSURI(), fSchemaInfo); newSchemaInfo.release(); redefSchemaInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE); fPreprocessedNodes->put((void*) redefineElem, fSchemaInfo); } return true; } void TraverseSchema::renameRedefinedComponents(const DOMElement* const redefineElem, SchemaInfo* const redefiningSchemaInfo, SchemaInfo* const redefinedSchemaInfo) { DOMElement* child = XUtil::getFirstChildElement(redefineElem); for (; child != 0; child = XUtil::getNextSiblingElement(child)) { const XMLCh* childName = child->getLocalName(); if (XMLString::equals(childName, SchemaSymbols::fgELT_ANNOTATION)) { continue; } // if component already redefined skip const XMLCh* typeName = getElementAttValue(child, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(typeName); if (fRedefineComponents->containsKey(childName, fStringPool->addOrFind(fBuffer.getRawBuffer()))) { continue; } // Rename const XMLCh* tmpChildName = fStringPool->getValueForId(fStringPool->addOrFind(childName)); if (validateRedefineNameChange(child, tmpChildName, typeName, 1, redefiningSchemaInfo)) { fixRedefinedSchema(child, redefinedSchemaInfo, tmpChildName, typeName, 1); } else { redefiningSchemaInfo->addFailedRedefine(child); } } } bool TraverseSchema::validateRedefineNameChange(const DOMElement* const redefineChildElem, const XMLCh* const redefineChildComponentName, const XMLCh* const redefineChildTypeName, const int redefineNameCounter, SchemaInfo* const redefiningSchemaInfo) { const XMLCh* baseTypeName = 0; unsigned int typeNameId = fStringPool->addOrFind(redefineChildTypeName); fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(redefineChildTypeName); int fullTypeNameId = fStringPool->addOrFind(fBuffer.getRawBuffer()); const XMLCh* typeNameStr = fStringPool->getValueForId(fullTypeNameId); restoreSchemaInfo(redefiningSchemaInfo); if (XMLString::equals(redefineChildComponentName,SchemaSymbols::fgELT_SIMPLETYPE)) { if (fDatatypeRegistry->getDatatypeValidator(typeNameStr)) { return false; } DOMElement* grandKid = XUtil::getFirstChildElement(redefineChildElem); if (grandKid && XMLString::equals(grandKid->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { grandKid = XUtil::getNextSiblingElement(grandKid); } if (grandKid == 0) { reportSchemaError(redefineChildElem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidSimpleType); return false; } else if(!XMLString::equals(grandKid->getLocalName(), SchemaSymbols::fgELT_RESTRICTION)) { reportSchemaError(grandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidSimpleType); return false; } baseTypeName = getElementAttValue(grandKid, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); const XMLCh* prefix = getPrefix(baseTypeName); const XMLCh* localPart = getLocalPart(baseTypeName); const XMLCh* uriStr = resolvePrefixToURI(grandKid, prefix); if (fTargetNSURI != (int) fURIStringPool->addOrFind(uriStr) || fStringPool->addOrFind(localPart) != typeNameId) { reportSchemaError(grandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidSimpleTypeBase); return false; } // now we have to do the renaming... getRedefineNewTypeName(baseTypeName, redefineNameCounter, fBuffer); grandKid->setAttribute(SchemaSymbols::fgATT_BASE, fBuffer.getRawBuffer()); fRedefineComponents->put((void*) SchemaSymbols::fgELT_SIMPLETYPE, fullTypeNameId, 0); } else if (XMLString::equals(redefineChildComponentName,SchemaSymbols::fgELT_COMPLEXTYPE)) { if (fComplexTypeRegistry->containsKey(typeNameStr)) { return false; } DOMElement* grandKid = XUtil::getFirstChildElement(redefineChildElem); if (grandKid && XMLString::equals(grandKid->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { grandKid = XUtil::getNextSiblingElement(grandKid); } if (grandKid == 0) { reportSchemaError(redefineChildElem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidComplexType); return false; } else { // have to go one more level down; let another pass worry whether complexType is valid. DOMElement* greatGrandKid = XUtil::getFirstChildElement(grandKid); if (greatGrandKid != 0 && XMLString::equals(greatGrandKid->getLocalName(), SchemaSymbols::fgELT_ANNOTATION)) { greatGrandKid = XUtil::getNextSiblingElement(greatGrandKid); } if (greatGrandKid == 0) { reportSchemaError(grandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidComplexType); return false; } else { const XMLCh* greatGrandKidName = greatGrandKid->getLocalName(); if (!XMLString::equals(greatGrandKidName, SchemaSymbols::fgELT_RESTRICTION) && !XMLString::equals(greatGrandKidName, SchemaSymbols::fgELT_EXTENSION)) { reportSchemaError(greatGrandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidComplexType); return false; } baseTypeName = getElementAttValue(greatGrandKid, SchemaSymbols::fgATT_BASE, DatatypeValidator::QName); const XMLCh* prefix = getPrefix(baseTypeName); const XMLCh* localPart = getLocalPart(baseTypeName); const XMLCh* uriStr = resolvePrefixToURI(greatGrandKid, prefix); if (fTargetNSURI != (int) fURIStringPool->addOrFind(uriStr) || fStringPool->addOrFind(localPart) != typeNameId) { reportSchemaError(greatGrandKid, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidComplexTypeBase); return false; } // now we have to do the renaming... getRedefineNewTypeName(baseTypeName, redefineNameCounter, fBuffer); greatGrandKid->setAttribute(SchemaSymbols::fgATT_BASE, fBuffer.getRawBuffer()); fRedefineComponents->put((void*) SchemaSymbols::fgELT_COMPLEXTYPE, fullTypeNameId, 0); } } } else if (XMLString::equals(redefineChildComponentName, SchemaSymbols::fgELT_GROUP)) { if (fGroupRegistry->containsKey(typeNameStr)) { return false; } int groupRefCount = changeRedefineGroup(redefineChildElem, redefineChildComponentName, redefineChildTypeName, redefineNameCounter); if (groupRefCount > 1) { reportSchemaError(redefineChildElem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_GroupRefCount); return false; } else if (groupRefCount == 0) { // put a dummy value, default is null. // when processing groups, we will check that table, if a value // is found, we need to do a particle derivation check. fRedefineComponents->put((void*) SchemaSymbols::fgELT_GROUP, fullTypeNameId, fSchemaInfo->getCurrentSchemaURL()); } else { fRedefineComponents->put((void*) SchemaSymbols::fgELT_GROUP, fullTypeNameId, 0); } } else if (XMLString::equals(redefineChildComponentName, SchemaSymbols::fgELT_ATTRIBUTEGROUP)) { if (fAttGroupRegistry->containsKey(redefineChildTypeName)) { return false; } int attGroupRefCount = changeRedefineGroup(redefineChildElem, redefineChildComponentName, redefineChildTypeName, redefineNameCounter); if (attGroupRefCount > 1) { reportSchemaError(redefineChildElem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_AttGroupRefCount); return false; } else if (attGroupRefCount == 0) { // put a dummy value, default is null. // when processing attributeGroups, we will check that table, if // a value is found, we need to check for attribute derivation ok // (by restriction) fRedefineComponents->put((void*) SchemaSymbols::fgELT_ATTRIBUTEGROUP, fullTypeNameId, fSchemaInfo->getCurrentSchemaURL()); } else { fRedefineComponents->put((void*) SchemaSymbols::fgELT_ATTRIBUTEGROUP, fullTypeNameId, 0); } } else { reportSchemaError ( redefineChildElem , XMLUni::fgXMLErrDomain , XMLErrs::Redefine_InvalidChild , redefineChildComponentName ); return false; } return true; } int TraverseSchema::changeRedefineGroup(const DOMElement* const redefineChildElem, const XMLCh* const redefineChildComponentName, const XMLCh* const redefineChildTypeName, const int redefineNameCounter) { int result = 0; DOMElement* child = XUtil::getFirstChildElement(redefineChildElem); for (; child != 0; child = XUtil::getNextSiblingElement(child)) { const XMLCh* name = child->getLocalName(); if (XMLString::equals(name, SchemaSymbols::fgELT_ANNOTATION)) { continue; } if (!XMLString::equals(name, redefineChildComponentName)) { result += changeRedefineGroup(child, redefineChildComponentName, redefineChildTypeName, redefineNameCounter); } else { const XMLCh* refName = getElementAttValue(child, SchemaSymbols::fgATT_REF, DatatypeValidator::QName); if (refName && *refName) { const XMLCh* prefix = getPrefix(refName); const XMLCh* localPart = getLocalPart(refName); const XMLCh* uriStr = resolvePrefixToURI(child, prefix); if (fTargetNSURI == (int) fURIStringPool->addOrFind(uriStr) && fStringPool->addOrFind(localPart) == fStringPool->addOrFind(redefineChildTypeName)) { // now we have to do the renaming... getRedefineNewTypeName(refName, redefineNameCounter, fBuffer); child->setAttribute(SchemaSymbols::fgATT_REF, fBuffer.getRawBuffer()); result++; if(XMLString::equals(redefineChildComponentName, SchemaSymbols::fgELT_GROUP)) { const XMLCh* minOccurs = getElementAttValue(child, SchemaSymbols::fgATT_MINOCCURS, DatatypeValidator::Decimal); const XMLCh* maxOccurs = getElementAttValue(child, SchemaSymbols::fgATT_MAXOCCURS, DatatypeValidator::Decimal); if (((maxOccurs && *maxOccurs) && !XMLString::equals(maxOccurs, fgValueOne)) || ((minOccurs && *minOccurs) && !XMLString::equals(minOccurs, fgValueOne))) { reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_InvalidGroupMinMax, redefineChildTypeName); } } } } // if ref was null some other stage of processing will flag the error } } return result; } void TraverseSchema::fixRedefinedSchema(const DOMElement* const elem, SchemaInfo* const redefinedSchemaInfo, const XMLCh* const redefineChildComponentName, const XMLCh* const redefineChildTypeName, const int redefineNameCounter) { bool foundIt = false; DOMElement* child = XUtil::getFirstChildElement(redefinedSchemaInfo->getRoot()); restoreSchemaInfo(redefinedSchemaInfo); for (; child != 0; child = XUtil::getNextSiblingElement(child)) { const XMLCh* name = child->getLocalName(); if (XMLString::equals(name, redefineChildComponentName)) { const XMLCh* infoItemName = getElementAttValue(child, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); if(!XMLString::equals(infoItemName, redefineChildTypeName)) { continue; } else { // found it! // now we have to do the renaming... foundIt = true; getRedefineNewTypeName(infoItemName, redefineNameCounter, fBuffer); child->setAttribute(SchemaSymbols::fgATT_NAME, fBuffer.getRawBuffer()); break; } } else if (XMLString::equals(name, SchemaSymbols::fgELT_REDEFINE)) { // need to search the redefine decl... for (DOMElement* redefChild = XUtil::getFirstChildElement(child); redefChild != 0; redefChild = XUtil::getNextSiblingElement(redefChild)) { const XMLCh* redefName = redefChild->getLocalName(); if (XMLString::equals(redefName, redefineChildComponentName)) { const XMLCh* infoItemName = getElementAttValue(redefChild, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName); if(!XMLString::equals(infoItemName, redefineChildTypeName)) { continue; } else { // found it! if (!openRedefinedSchema(child)) { redefinedSchemaInfo->addFailedRedefine(child); return; } foundIt = true; SchemaInfo* reRedefinedSchemaInfo = fSchemaInfo; if (validateRedefineNameChange(redefChild, redefineChildComponentName, redefineChildTypeName, redefineNameCounter + 1, redefinedSchemaInfo)) { fixRedefinedSchema(redefChild, reRedefinedSchemaInfo, redefineChildComponentName, redefineChildTypeName, redefineNameCounter + 1); // now we have to do the renaming... getRedefineNewTypeName(infoItemName, redefineNameCounter, fBuffer); const XMLCh* newInfoItemName = fStringPool->getValueForId(fStringPool->addOrFind(fBuffer.getRawBuffer())); redefChild->setAttribute(SchemaSymbols::fgATT_NAME, newInfoItemName); // and we now know we will traverse this, so set fRedefineComponents appropriately... fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(newInfoItemName); } else { fixRedefinedSchema(redefChild, reRedefinedSchemaInfo, redefineChildComponentName, redefineChildTypeName, redefineNameCounter); redefinedSchemaInfo->addFailedRedefine(redefChild); // and we now know we will traverse this, so set fRedefineComponents appropriately... fBuffer.set(fTargetNSURIString); fBuffer.append(chComma); fBuffer.append(infoItemName); } unsigned int infoItemNameId = fStringPool->addOrFind(fBuffer.getRawBuffer()); if (!fRedefineComponents->containsKey(redefineChildComponentName, infoItemNameId)) { fRedefineComponents->put((void*) redefineChildComponentName, infoItemNameId, 0); } break; } } } //for if (foundIt) { break; } } } //for if(!foundIt) { reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Redefine_DeclarationNotFound, redefineChildTypeName); } } bool TraverseSchema::isSubstitutionGroupCircular(SchemaElementDecl* const elemDecl, SchemaElementDecl* const subsElemDecl) { if (elemDecl == subsElemDecl) return true; SchemaElementDecl* tmpElemDecl = subsElemDecl->getSubstitutionGroupElem(); while (tmpElemDecl) { if (tmpElemDecl == elemDecl) return true; tmpElemDecl = tmpElemDecl->getSubstitutionGroupElem(); } return false; } // --------------------------------------------------------------------------- // TraverseSchema: Error reporting methods // --------------------------------------------------------------------------- void TraverseSchema::reportSchemaError(const XSDLocator* const aLocator, const XMLCh* const msgDomain, const int errorCode) { fXSDErrorReporter.emitError(errorCode, msgDomain, aLocator); } void TraverseSchema::reportSchemaError(const XSDLocator* const aLocator, const XMLCh* const msgDomain, const int errorCode, const XMLCh* const text1, const XMLCh* const text2, const XMLCh* const text3, const XMLCh* const text4) { fXSDErrorReporter.emitError(errorCode, msgDomain, aLocator, text1, text2, text3, text4, fMemoryManager); } void TraverseSchema::reportSchemaError(const DOMElement* const elem, const XMLCh* const msgDomain, const int errorCode) { fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, ((XSDElementNSImpl*) elem)->getLineNo(), ((XSDElementNSImpl*) elem)->getColumnNo()); fXSDErrorReporter.emitError(errorCode, msgDomain, fLocator); } void TraverseSchema::reportSchemaError(const DOMElement* const elem, const XMLCh* const msgDomain, const int errorCode, const XMLCh* const text1, const XMLCh* const text2, const XMLCh* const text3, const XMLCh* const text4) { fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, ((XSDElementNSImpl*) elem)->getLineNo(), ((XSDElementNSImpl*) elem)->getColumnNo()); fXSDErrorReporter.emitError(errorCode, msgDomain, fLocator, text1, text2, text3, text4, fMemoryManager); } void TraverseSchema::reportSchemaError(const DOMElement* const elem, const XMLException& except) { fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0, ((XSDElementNSImpl*) elem)->getLineNo(), ((XSDElementNSImpl*) elem)->getColumnNo()); fXSDErrorReporter.emitError(except, fLocator); } // --------------------------------------------------------------------------- // TraverseSchema: Init/CleanUp methods // --------------------------------------------------------------------------- void TraverseSchema::init() { fXSDErrorReporter.setErrorReporter(fErrorReporter); fXSDErrorReporter.setExitOnFirstFatal(fScanner->getExitOnFirstFatal()); fFullConstraintChecking = fScanner->getValidationSchemaFullChecking(); fDatatypeRegistry = fSchemaGrammar->getDatatypeRegistry(); fStringPool = fGrammarResolver->getStringPool(); fEmptyNamespaceURI = fScanner->getEmptyNamespaceId(); fCurrentTypeNameStack = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); fCurrentGroupStack = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); fGlobalDeclarations = (ValueVectorOf**) fMemoryManager->allocate ( ENUM_ELT_SIZE * sizeof(ValueVectorOf*) );//new ValueVectorOf*[ENUM_ELT_SIZE]; memset(fGlobalDeclarations, 0, ENUM_ELT_SIZE * sizeof(ValueVectorOf*)); for(unsigned int i=0; i < ENUM_ELT_SIZE; i++) fGlobalDeclarations[i] = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); fNonXSAttList = new (fMemoryManager) ValueVectorOf(4, fMemoryManager); fNotationRegistry = new (fMemoryManager) RefHash2KeysTableOf(13, (bool) false, fMemoryManager); fPreprocessedNodes = new (fMemoryManager) RefHashTableOf ( 29 , false , fMemoryManager ); fLocator = new (fMemoryManager) XSDLocator(); fDeclStack = new (fMemoryManager) ValueVectorOf(16, fMemoryManager); } void TraverseSchema::cleanUp() { delete fCurrentTypeNameStack; delete fCurrentGroupStack; if (fGlobalDeclarations) { for(unsigned int i=0; i < ENUM_ELT_SIZE; i++) delete fGlobalDeclarations[i]; fMemoryManager->deallocate(fGlobalDeclarations);//delete [] fGlobalDeclarations; } delete fNonXSAttList; delete fImportedNSList; delete fNotationRegistry; delete fRedefineComponents; delete fIdentityConstraintNames; delete fDeclStack; delete fIC_ElementsNS; delete fIC_NodeListNS; delete fPreprocessedNodes; delete fLocator; delete fParser; } void TraverseSchema::processElemDeclAttrs(const DOMElement* const elem, SchemaElementDecl* const elemDecl, const XMLCh*& valueConstraint, bool isTopLevel) { int elementMiscFlags = 0; const XMLCh* fixedVal = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED); const XMLCh* nillable = getElementAttValue(elem, SchemaSymbols::fgATT_NILLABLE, DatatypeValidator::Boolean); // check constraint value valueConstraint = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT); if (fixedVal) { elementMiscFlags |= SchemaSymbols::XSD_FIXED; // if both default and fixed, emit an error if (valueConstraint) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::ElementWithFixedAndDefault, getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName)); // set constraint value to the fixed one valueConstraint = fixedVal; } // check nillable if (nillable && *nillable) { if (XMLString::equals(nillable, SchemaSymbols::fgATTVAL_TRUE) || XMLString::equals(nillable, fgValueOne)) { elementMiscFlags |= SchemaSymbols::XSD_NILLABLE; } } if (isTopLevel) { const XMLCh* bAbstract = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT, DatatypeValidator::Boolean); if (bAbstract && *bAbstract) { if (XMLString::equals(bAbstract, SchemaSymbols::fgATTVAL_TRUE) || XMLString::equals(bAbstract, fgValueOne)) { elementMiscFlags |= SchemaSymbols::XSD_ABSTRACT; } } elemDecl->setFinalSet(parseFinalSet(elem, EC_Final)); } elemDecl->setBlockSet(parseBlockSet(elem, ES_Block)); elemDecl->setMiscFlags(elementMiscFlags); } void TraverseSchema::processElemDeclIC(DOMElement* const icElem, SchemaElementDecl* const elemDecl) { // key/keyref/unique processing ValueVectorOf* icNodes = 0; DOMElement* ic = icElem; while (ic != 0) { if (XMLString::equals(ic->getLocalName(), SchemaSymbols::fgELT_KEY)) { traverseKey(ic, elemDecl); } else if (XMLString::equals(ic->getLocalName(), SchemaSymbols::fgELT_UNIQUE)) { traverseUnique(ic, elemDecl); } else { if (!icNodes) { icNodes = new (fGrammarPoolMemoryManager) ValueVectorOf(8, fGrammarPoolMemoryManager); } icNodes->addElement(ic); } ic = XUtil::getNextSiblingElementNS( ic, fgIdentityConstraints, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, 3); } if (icNodes) { if (!fIC_ElementsNS) { fIC_ElementsNS = new (fMemoryManager) RefHashTableOf(13, fMemoryManager); fIC_NodeListNS = new (fMemoryManager) RefHashTableOf, PtrHasher>(29, true, fMemoryManager); } fIC_Elements = fIC_ElementsNS->get(fTargetNSURIString); if (!fIC_Elements) { fIC_Elements = new (fMemoryManager) ValueVectorOf(8, fMemoryManager); fIC_ElementsNS->put((void*) fTargetNSURIString, fIC_Elements); } fIC_NodeListNS->put(elemDecl, icNodes); fIC_Elements->addElement(elemDecl); } } bool TraverseSchema::checkElemDeclValueConstraint(const DOMElement* const elem, SchemaElementDecl* const elemDecl, const XMLCh* const valConstraint, ComplexTypeInfo* const typeInfo, DatatypeValidator* const validator) { bool isValid = false; if (validator) { if (validator->getType() == DatatypeValidator::ID) reportSchemaError( elem, XMLUni::fgXMLErrDomain, XMLErrs::ElemIDValueConstraint , elemDecl->getBaseName(), valConstraint ); try { const XMLCh* valueToCheck = valConstraint; short wsFacet = validator->getWSFacet(); if((wsFacet == DatatypeValidator::REPLACE && !XMLString::isWSReplaced(valueToCheck)) || (wsFacet == DatatypeValidator::COLLAPSE && !XMLString::isWSCollapsed(valueToCheck))) { XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager); ArrayJanitor tempURIName(normalizedValue, fMemoryManager); if(wsFacet == DatatypeValidator::REPLACE) XMLString::replaceWS(normalizedValue, fMemoryManager); else if(wsFacet == DatatypeValidator::COLLAPSE) XMLString::collapseWS(normalizedValue, fMemoryManager); valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue)); } validator->validate(valueToCheck,0,fMemoryManager); XMLCh* canonical = (XMLCh*) validator->getCanonicalRepresentation(valueToCheck, fMemoryManager); ArrayJanitor tempCanonical(canonical, fMemoryManager); if(!XMLString::equals(canonical, valueToCheck)) { validator->validate(canonical, 0, fMemoryManager); valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(canonical)); } elemDecl->setDefaultValue(valueToCheck); isValid = true; } catch(const XMLException& excep) { reportSchemaError(elem, excep); } catch(const OutOfMemoryException&) { throw; } catch(...) { reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valConstraint); } } if (typeInfo) { int contentSpecType = typeInfo->getContentType(); if (contentSpecType != SchemaElementDecl::Simple && contentSpecType != SchemaElementDecl::Mixed_Simple && contentSpecType != SchemaElementDecl::Mixed_Complex) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotSimpleOrMixedElement, elemDecl->getBaseName()); if (((contentSpecType == SchemaElementDecl::Mixed_Complex || contentSpecType == SchemaElementDecl::Mixed_Simple) && !emptiableParticle(typeInfo->getContentSpec()))) reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::EmptiableMixedContent, elemDecl->getBaseName()); } return isValid; } void TraverseSchema::processSubstitutionGroup(const DOMElement* const elem, SchemaElementDecl* const elemDecl, ComplexTypeInfo*& typeInfo, DatatypeValidator*& validator, const XMLCh* const subsElemQName) { NamespaceScopeManager nsMgr(elem, fSchemaInfo, this); SchemaElementDecl* subsElemDecl = getGlobalElemDecl(elem, subsElemQName); if (subsElemDecl) { if (isSubstitutionGroupCircular(elemDecl, subsElemDecl)) { reportSchemaError( elem , XMLUni::fgXMLErrDomain , XMLErrs::CircularSubsGroup, elemDecl->getBaseName()); } else { // Check for substitution validity constraint // Substitution allowed (block and blockDefault) && same type if (isSubstitutionGroupValid(elem, subsElemDecl, typeInfo, validator, elemDecl->getBaseName())) { elemDecl->setSubstitutionGroupElem(subsElemDecl); // if type information is missing, use subsGroup one if (!typeInfo && !validator) { typeInfo = subsElemDecl->getComplexTypeInfo(); validator = subsElemDecl->getDatatypeValidator(); if (validator) { elemDecl->setDatatypeValidator(validator); elemDecl->setModelType(SchemaElementDecl::Simple); } else if (typeInfo) { elemDecl->setComplexTypeInfo(typeInfo); elemDecl->setModelType((SchemaElementDecl::ModelTypes)typeInfo->getContentType()); } } XMLCh* subsElemBaseName = subsElemDecl->getBaseName(); int subsElemURI = subsElemDecl->getURI(); ValueVectorOf* subsElements = fValidSubstitutionGroups->get(subsElemBaseName, subsElemURI); if (!subsElements && fTargetNSURI != subsElemURI) { SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(fURIStringPool->getValueForId(subsElemURI)); if (aGrammar) { subsElements = aGrammar->getValidSubstitutionGroups()->get(subsElemBaseName, subsElemURI); if (subsElements) { subsElements = new (fGrammarPoolMemoryManager) ValueVectorOf(*subsElements); fValidSubstitutionGroups->put(subsElemBaseName, subsElemURI, subsElements); } else if (fSchemaInfo->circularImportExist(subsElemURI)) { aGrammar->getValidSubstitutionGroups()->put( subsElemBaseName, subsElemURI, new (fGrammarPoolMemoryManager) ValueVectorOf(8, fGrammarPoolMemoryManager)); } } } if (!subsElements) { subsElements = new (fGrammarPoolMemoryManager) ValueVectorOf(8, fGrammarPoolMemoryManager); fValidSubstitutionGroups->put(subsElemBaseName, subsElemURI, subsElements); } subsElements->addElement(elemDecl); // update related subs. info in case of circular import BaseRefVectorEnumerator importingEnum = fSchemaInfo->getImportingListEnumerator(); while (importingEnum.hasMoreElements()) { const SchemaInfo& curRef = importingEnum.nextElement(); SchemaGrammar* aGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(curRef.getTargetNSURIString()); ValueVectorOf* subsElemList = aGrammar->getValidSubstitutionGroups()->get(subsElemBaseName, subsElemURI); if (subsElemList && !subsElemList->containsElement(elemDecl)) subsElemList->addElement(elemDecl); } buildValidSubstitutionListB(elem, elemDecl, subsElemDecl); buildValidSubstitutionListF(elem, elemDecl, subsElemDecl); } } } } void TraverseSchema::processAttValue(const XMLCh* const attVal, XMLBuffer& aBuf) { // REVISIT-KN: assuming that attVal is not NULL // // normally, nothing will happen const XMLCh* srcVal = attVal; XMLCh nextCh = *srcVal; while (nextCh) { if (nextCh <= chCloseAngle) { switch (nextCh) { case chDoubleQuote: aBuf.append(chAmpersand); aBuf.append(XMLUni::fgQuot); aBuf.append(chSemiColon); break; case chSingleQuote: aBuf.append(chAmpersand); aBuf.append(XMLUni::fgApos); aBuf.append(chSemiColon); break; case chCloseAngle: aBuf.append(chAmpersand); aBuf.append(XMLUni::fgGT); aBuf.append(chSemiColon); break; case chOpenAngle: aBuf.append(chAmpersand); aBuf.append(XMLUni::fgLT); aBuf.append(chSemiColon); break; case chAmpersand: aBuf.append(chAmpersand); aBuf.append(XMLUni::fgAmp); aBuf.append(chSemiColon); break; default: aBuf.append(nextCh); break; } // end switch } else aBuf.append(nextCh); nextCh = *++srcVal; } } XSAnnotation* TraverseSchema::generateSyntheticAnnotation(const DOMElement* const elem , ValueVectorOf* nonXSAttList) { const XMLCh* prefix = elem->getPrefix(); ValueHashTableOf* listOfURIs = new (fMemoryManager) ValueHashTableOf(29, fMemoryManager); bool sawXMLNS = false; fBuffer.reset(); fBuffer.append(chOpenAngle); if (prefix) { fBuffer.append(prefix); fBuffer.append(chColon); } fBuffer.append(SchemaSymbols::fgELT_ANNOTATION); // next is the nonXSAttList names & values XMLSize_t nonXSAttSize = nonXSAttList->size(); for (XMLSize_t i=0; ielementAt(i); fBuffer.append(chSpace); fBuffer.append(attNode->getNodeName()); fBuffer.append(chEqual); fBuffer.append(chDoubleQuote); processAttValue(attNode->getNodeValue(), fBuffer); fBuffer.append(chDoubleQuote); } // next is the namespaces on the elem DOMElement* currentElem = (DOMElement*) elem; DOMNamedNodeMap* eltAttrs; XMLSize_t attrCount; do { eltAttrs = currentElem->getAttributes(); attrCount = eltAttrs->getLength(); for (XMLSize_t j = 0; j < attrCount; j++) { DOMNode* attribute = eltAttrs->item(j); const XMLCh* attName = attribute->getNodeName(); if (XMLString::startsWith(attName, XMLUni::fgXMLNSColonString)) { if (!listOfURIs->containsKey((void*) attName)) { listOfURIs->put((void*) attName, 0); fBuffer.append(chSpace); fBuffer.append(attName); fBuffer.append(chEqual); fBuffer.append(chDoubleQuote); processAttValue(attribute->getNodeValue(), fBuffer); fBuffer.append(chDoubleQuote); } } else if (!sawXMLNS && XMLString::equals(attName, XMLUni::fgXMLNSString)) { fBuffer.append(chSpace); fBuffer.append(attName); fBuffer.append(chEqual); fBuffer.append(chDoubleQuote); processAttValue(attribute->getNodeValue(), fBuffer); fBuffer.append(chDoubleQuote); sawXMLNS = true; } } currentElem = (DOMElement*) currentElem->getParentNode(); } while (currentElem != fSchemaInfo->getRoot()->getParentNode()); delete listOfURIs; fBuffer.append(chCloseAngle); fBuffer.append(chLF); fBuffer.append(chOpenAngle); if (prefix) { fBuffer.append(prefix); fBuffer.append(chColon); } fBuffer.append(SchemaSymbols::fgELT_DOCUMENTATION); fBuffer.append(chCloseAngle); fBuffer.append(fgSynthetic_Annotation); fBuffer.append(chOpenAngle); fBuffer.append(chForwardSlash); if (prefix) { fBuffer.append(prefix); fBuffer.append(chColon); } fBuffer.append(SchemaSymbols::fgELT_DOCUMENTATION); fBuffer.append(chCloseAngle); fBuffer.append(chLF); fBuffer.append(chOpenAngle); fBuffer.append(chForwardSlash); if (prefix) { fBuffer.append(prefix); fBuffer.append(chColon); } fBuffer.append(SchemaSymbols::fgELT_ANNOTATION); fBuffer.append(chCloseAngle); XSAnnotation* annot = new (fGrammarPoolMemoryManager) XSAnnotation(fBuffer.getRawBuffer(), fGrammarPoolMemoryManager); annot->setLineCol( ((XSDElementNSImpl*)elem)->getLineNo() , ((XSDElementNSImpl*)elem)->getColumnNo() ); annot->setSystemId(fSchemaInfo->getCurrentSchemaURL()); return annot; } class AnnotationErrorReporter : public XMLErrorReporter { public: AnnotationErrorReporter(XMLErrorReporter* chainedErrorReporter) { fErrorReporter = chainedErrorReporter; setSystemIdAndPosition(NULL, 0, 0); } void setSystemIdAndPosition(const XMLCh* systemId, XMLFileLoc line, XMLFileLoc column) { fSystemId=systemId; fLine=line; fColumn=column; } virtual void error ( const unsigned int errCode , const XMLCh* const errDomain , const ErrTypes type , const XMLCh* const errorText , const XMLCh* const /*systemId*/ , const XMLCh* const publicId , const XMLFileLoc lineNum , const XMLFileLoc colNum ) { if(fErrorReporter) fErrorReporter->error(errCode, errDomain, type, errorText, fSystemId, publicId, fLine+lineNum-1, lineNum==1?fColumn+colNum:colNum); } virtual void resetErrors() {} protected: XMLErrorReporter* fErrorReporter; const XMLCh* fSystemId; XMLFileLoc fLine, fColumn; }; void TraverseSchema::validateAnnotations() { MemoryManager *memMgr = fMemoryManager; RefHashTableOfEnumerator xsAnnotationEnum = RefHashTableOfEnumerator (fSchemaGrammar->getAnnotations(), false, memMgr); XSAnnotation& xsAnnot = xsAnnotationEnum.nextElement(); XSAnnotation* nextAnnot; // create schema grammar SchemaGrammar *grammar = new (memMgr) SchemaGrammar(memMgr); grammar->setComplexTypeRegistry(new (memMgr) RefHashTableOf(29, memMgr)); grammar->setGroupInfoRegistry(new (memMgr) RefHashTableOf(13, memMgr)); grammar->setAttGroupInfoRegistry(new (memMgr) RefHashTableOf(13, memMgr)); grammar->setAttributeDeclRegistry(new (memMgr) RefHashTableOf(29, memMgr)); grammar->setValidSubstitutionGroups(new (memMgr) RefHash2KeysTableOf(29, memMgr)); grammar->setTargetNamespace(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) grammar->getGrammarDescription(); gramDesc->setTargetNamespace(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); // setup components of annotation grammar SchemaElementDecl* annotElemDecl = new (memMgr) SchemaElementDecl ( XMLUni::fgZeroLenString , SchemaSymbols::fgELT_ANNOTATION , fURIStringPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA) , SchemaElementDecl::Mixed_Complex, Grammar::TOP_LEVEL_SCOPE , memMgr ); annotElemDecl->setCreateReason(XMLElementDecl::Declared); grammar->putElemDecl(annotElemDecl); ComplexTypeInfo* complexType = new (memMgr) ComplexTypeInfo(memMgr); complexType->setAnonymous(); complexType->setContentType(SchemaElementDecl::Mixed_Complex); annotElemDecl->setComplexTypeInfo(complexType); fBuffer.set(SchemaSymbols::fgURI_SCHEMAFORSCHEMA); fBuffer.append(chComma); fBuffer.append(chLatin_C); fBuffer.append(chDigit_0); const XMLCh* fullName = fStringPool->getValueForId(fStringPool->addOrFind(fBuffer.getRawBuffer())); grammar->getComplexTypeRegistry()->put((void*) fullName, complexType); complexType->setTypeName(fullName); complexType->setAttWildCard ( new (memMgr) SchemaAttDef ( XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, fEmptyNamespaceURI, XMLAttDef::Any_Any, XMLAttDef::ProcessContents_Lax, memMgr ) ); SchemaElementDecl* appInfoElemDecl = new (memMgr) SchemaElementDecl ( XMLUni::fgZeroLenString , SchemaSymbols::fgELT_APPINFO , fURIStringPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA) , SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE , memMgr ); appInfoElemDecl->setCreateReason(XMLElementDecl::Declared); appInfoElemDecl->setAttWildCard ( new (memMgr) SchemaAttDef ( XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, fEmptyNamespaceURI, XMLAttDef::Any_Any, XMLAttDef::ProcessContents_Lax, memMgr ) ); grammar->putElemDecl(appInfoElemDecl); complexType->addElement(appInfoElemDecl); SchemaElementDecl* docElemDecl = new (memMgr) SchemaElementDecl ( XMLUni::fgZeroLenString , SchemaSymbols::fgELT_DOCUMENTATION , fURIStringPool->addOrFind(SchemaSymbols::fgURI_SCHEMAFORSCHEMA) , SchemaElementDecl::Any, Grammar::TOP_LEVEL_SCOPE , memMgr ); docElemDecl->setCreateReason(XMLElementDecl::Declared); docElemDecl->setAttWildCard ( new (memMgr) SchemaAttDef ( XMLUni::fgZeroLenString, XMLUni::fgZeroLenString, fEmptyNamespaceURI, XMLAttDef::Any_Any, XMLAttDef::ProcessContents_Lax, memMgr ) ); grammar->putElemDecl(docElemDecl); complexType->addElement(docElemDecl); ContentSpecNode* left = new (memMgr) ContentSpecNode(appInfoElemDecl, memMgr); ContentSpecNode* right = new (memMgr) ContentSpecNode(docElemDecl, memMgr); ContentSpecNode* root = new (memMgr) ContentSpecNode(ContentSpecNode::ModelGroupChoice , left , right , true , true , memMgr); root->setMinOccurs(0); root->setMaxOccurs(SchemaSymbols::XSD_UNBOUNDED); complexType->setContentSpec(root); // create input source to scan MemBufInputSource* memBufIS = new (memMgr) MemBufInputSource ( (const XMLByte*)xsAnnot.getAnnotationString() , XMLString::stringLen(xsAnnot.getAnnotationString())*sizeof(XMLCh) , SchemaSymbols::fgELT_ANNOTATION , false , memMgr ); Janitor janMemBuf(memBufIS); memBufIS->setEncoding(XMLUni::fgXMLChEncodingString); memBufIS->setCopyBufToStream(false); XSAXMLScanner *scanner = new (memMgr) XSAXMLScanner ( fGrammarResolver, fURIStringPool, grammar, memMgr ); Janitor janScanner(scanner); AnnotationErrorReporter annErrReporter(fErrorReporter); scanner->setErrorReporter(&annErrReporter); XMLFileLoc line, col; xsAnnot.getLineCol(line, col); annErrReporter.setSystemIdAndPosition(xsAnnot.getSystemId(), line, col); scanner->scanDocument(*memBufIS); nextAnnot = xsAnnot.getNext(); while (nextAnnot || xsAnnotationEnum.hasMoreElements()) { if (nextAnnot) { memBufIS->resetMemBufInputSource((const XMLByte*)nextAnnot->getAnnotationString() , XMLString::stringLen(nextAnnot->getAnnotationString())*sizeof(XMLCh)); nextAnnot->getLineCol(line, col); annErrReporter.setSystemIdAndPosition(nextAnnot->getSystemId(), line, col); nextAnnot = nextAnnot->getNext(); } else { XSAnnotation& xsAnnot = xsAnnotationEnum.nextElement(); memBufIS->resetMemBufInputSource((const XMLByte*)xsAnnot.getAnnotationString() , XMLString::stringLen(xsAnnot.getAnnotationString())*sizeof(XMLCh)); xsAnnot.getLineCol(line, col); annErrReporter.setSystemIdAndPosition(xsAnnot.getSystemId(), line, col); nextAnnot = xsAnnot.getNext(); } scanner->scanDocument(*memBufIS); } } const XMLCh* TraverseSchema::getElementAttValue(const DOMElement* const elem, const XMLCh* const attName, const DatatypeValidator::ValidatorType attType /* = UnKnown */) { DOMAttr* attNode = elem->getAttributeNode(attName); if (attNode == 0) { return 0; } const XMLCh* attValue = attNode->getValue(); if (attType < DatatypeValidator::ID) { static bool bInitialized = false; static short wsFacets[DatatypeValidator::ID] = {0}; if(!bInitialized) { bInitialized=true; DVHashTable* registry = DatatypeValidatorFactory::getBuiltInRegistry(); wsFacets[DatatypeValidator::String] = registry->get(SchemaSymbols::fgDT_STRING)->getWSFacet(); wsFacets[DatatypeValidator::AnyURI] = registry->get(SchemaSymbols::fgDT_ANYURI)->getWSFacet(); wsFacets[DatatypeValidator::QName] = registry->get(SchemaSymbols::fgDT_QNAME)->getWSFacet(); wsFacets[DatatypeValidator::Name] = registry->get(SchemaSymbols::fgDT_NAME)->getWSFacet(); wsFacets[DatatypeValidator::NCName] = registry->get(SchemaSymbols::fgDT_NCNAME)->getWSFacet(); wsFacets[DatatypeValidator::Boolean] = registry->get(SchemaSymbols::fgDT_BOOLEAN)->getWSFacet(); wsFacets[DatatypeValidator::Float] = registry->get(SchemaSymbols::fgDT_FLOAT)->getWSFacet(); wsFacets[DatatypeValidator::Double] = registry->get(SchemaSymbols::fgDT_DOUBLE)->getWSFacet(); wsFacets[DatatypeValidator::Decimal] = registry->get(SchemaSymbols::fgDT_DECIMAL)->getWSFacet(); wsFacets[DatatypeValidator::HexBinary] = registry->get(SchemaSymbols::fgDT_HEXBINARY)->getWSFacet(); wsFacets[DatatypeValidator::Base64Binary]= registry->get(SchemaSymbols::fgDT_BASE64BINARY)->getWSFacet(); wsFacets[DatatypeValidator::Duration] = registry->get(SchemaSymbols::fgDT_DURATION)->getWSFacet(); wsFacets[DatatypeValidator::DateTime] = registry->get(SchemaSymbols::fgDT_DATETIME)->getWSFacet(); wsFacets[DatatypeValidator::Date] = registry->get(SchemaSymbols::fgDT_DATE)->getWSFacet(); wsFacets[DatatypeValidator::Time] = registry->get(SchemaSymbols::fgDT_TIME)->getWSFacet(); wsFacets[DatatypeValidator::MonthDay] = registry->get(SchemaSymbols::fgDT_MONTHDAY)->getWSFacet(); wsFacets[DatatypeValidator::YearMonth] = registry->get(SchemaSymbols::fgDT_YEARMONTH)->getWSFacet(); wsFacets[DatatypeValidator::Year] = registry->get(SchemaSymbols::fgDT_YEAR)->getWSFacet(); wsFacets[DatatypeValidator::Month] = registry->get(SchemaSymbols::fgDT_MONTH)->getWSFacet(); wsFacets[DatatypeValidator::Day] = registry->get(SchemaSymbols::fgDT_DAY)->getWSFacet(); } short wsFacet = wsFacets[attType]; if((wsFacet == DatatypeValidator::REPLACE && !XMLString::isWSReplaced(attValue)) || (wsFacet == DatatypeValidator::COLLAPSE && !XMLString::isWSCollapsed(attValue))) { XMLCh* normalizedValue=XMLString::replicate(attValue, fMemoryManager); ArrayJanitor tempName(normalizedValue, fMemoryManager); if(wsFacet == DatatypeValidator::REPLACE) XMLString::replaceWS(normalizedValue, fMemoryManager); else if(wsFacet == DatatypeValidator::COLLAPSE) XMLString::collapseWS(normalizedValue, fMemoryManager); if (!*normalizedValue) return XMLUni::fgZeroLenString; return fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue)); } } return attValue; } XERCES_CPP_NAMESPACE_END /** * End of file TraverseSchema.cpp */