TraverseSchema.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:302k
- /*
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001-2002 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Xerces" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation, and was
- * originally based on software copyright (c) 2001, International
- * Business Machines, Inc., http://www.ibm.com . For more information
- * on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
- /*
- * $Id: TraverseSchema.cpp,v 1.75 2003/05/26 22:05:01 knoaman Exp $
- */
- // ---------------------------------------------------------------------------
- // Includes
- // ---------------------------------------------------------------------------
- #include <xercesc/validators/schema/TraverseSchema.hpp>
- #include <xercesc/framework/XMLEntityHandler.hpp>
- #include <xercesc/framework/XMLValidityCodes.hpp>
- #include <xercesc/validators/schema/identity/IC_Key.hpp>
- #include <xercesc/validators/schema/identity/IC_KeyRef.hpp>
- #include <xercesc/validators/schema/identity/IC_Unique.hpp>
- #include <xercesc/validators/schema/identity/IC_Field.hpp>
- #include <xercesc/validators/schema/identity/IC_Selector.hpp>
- #include <xercesc/validators/schema/identity/XercesXPath.hpp>
- #include <xercesc/util/XMLStringTokenizer.hpp>
- #include <xercesc/validators/schema/XUtil.hpp>
- #include <xercesc/validators/common/GrammarResolver.hpp>
- #include <xercesc/internal/XMLReader.hpp>
- #include <xercesc/validators/schema/ComplexTypeInfo.hpp>
- #include <xercesc/validators/schema/NamespaceScope.hpp>
- #include <xercesc/validators/schema/SchemaAttDefList.hpp>
- #include <xercesc/internal/XMLScanner.hpp>
- #include <xercesc/framework/LocalFileInputSource.hpp>
- #include <xercesc/framework/URLInputSource.hpp>
- #include <xercesc/validators/schema/identity/XPathException.hpp>
- #include <xercesc/validators/schema/GeneralAttributeCheck.hpp>
- #include <xercesc/validators/schema/XercesGroupInfo.hpp>
- #include <xercesc/validators/schema/XercesAttGroupInfo.hpp>
- #include <xercesc/validators/schema/XSDLocator.hpp>
- #include <xercesc/validators/schema/XSDDOMParser.hpp>
- #include <xercesc/util/HashPtr.hpp>
- #include <xercesc/dom/DOMNamedNodeMap.hpp>
- #include <xercesc/dom/impl/XSDElementNSImpl.hpp>
- XERCES_CPP_NAMESPACE_BEGIN
- // ---------------------------------------------------------------------------
- // TraverseSchema: Local declaration
- // ---------------------------------------------------------------------------
- typedef RefVectorOf<DatatypeValidator> DVRefVector;
- // ---------------------------------------------------------------------------
- // TraverseSchema: Static member data
- // ---------------------------------------------------------------------------
- // ---------------------------------------------------------------------------
- // TraverseSchema: Local const data
- // ---------------------------------------------------------------------------
- const XMLCh fgXMLNS_Str[] =
- {
- chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chColon, chNull
- };
- const XMLCh fgAnonSNamePrefix[] =
- {
- chLatin_S, chNull
- };
- const XMLCh fgAnonCNamePrefix[] =
- {
- chLatin_C, chNull
- };
- const XMLCh fgUnbounded[] =
- {
- chLatin_u, chLatin_n, chLatin_b, chLatin_o, chLatin_u, chLatin_n, chLatin_d,
- chLatin_e, chLatin_d, chNull
- };
- const XMLCh fgSkip[] =
- {
- chLatin_s, chLatin_k, chLatin_i, chLatin_p, chNull
- };
- const XMLCh fgLax[] =
- {
- chLatin_l, chLatin_a, chLatin_x, chNull
- };
- const XMLCh fgStrict[] =
- {
- chLatin_s, chLatin_t, chLatin_r, chLatin_i, chLatin_c, chLatin_t, chNull
- };
- const XMLCh fgValueOne[] =
- {
- chDigit_1, chNull
- };
- const XMLCh fgValueZero[] =
- {
- chDigit_0, chNull
- };
- const XMLCh fgForwardSlash[] =
- {
- chForwardSlash, chNull
- };
- const XMLCh fgDot[] =
- {
- chPeriod, chNull
- };
- const XMLCh fgDotForwardSlash[] =
- {
- chPeriod, chForwardSlash, chNull
- };
- const XMLCh* fgIdentityConstraints[] =
- {
- SchemaSymbols::fgELT_UNIQUE,
- SchemaSymbols::fgELT_KEY,
- SchemaSymbols::fgELT_KEYREF
- };
- // 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
- };
- // ---------------------------------------------------------------------------
- // TraverseSchema: Constructors and Destructor
- // ---------------------------------------------------------------------------
- TraverseSchema::TraverseSchema( DOMElement* const schemaRoot
- , XMLStringPool* const uriStringPool
- , SchemaGrammar* const schemaGrammar
- , GrammarResolver* const grammarResolver
- , XMLScanner* const xmlScanner
- , const XMLCh* const schemaURL
- , XMLEntityHandler* const entityHandler
- , XMLErrorReporter* const errorReporter
- , MemoryManager* const manager)
- : fFullConstraintChecking(false)
- , fTargetNSURI(-1)
- , fEmptyNamespaceURI(-1)
- , fCurrentScope(Grammar::TOP_LEVEL_SCOPE)
- , fScopeCount(0)
- , fAnonXSTypeCount(0)
- , fCircularCheckIndex(0)
- , fTargetNSURIString(0)
- , fDatatypeRegistry(0)
- , fGrammarResolver(grammarResolver)
- , fSchemaGrammar(schemaGrammar)
- , fEntityHandler(entityHandler)
- , fErrorReporter(errorReporter)
- , fURIStringPool(uriStringPool)
- , fStringPool(0)
- , fBuffer(1023, manager)
- , fScanner(xmlScanner)
- , fNamespaceScope(0)
- , fAttributeDeclRegistry(0)
- , fComplexTypeRegistry(0)
- , fGroupRegistry(0)
- , fAttGroupRegistry(0)
- , fSchemaInfoList(0)
- , fSchemaInfo(0)
- , fCurrentGroupInfo(0)
- , fCurrentAttGroupInfo(0)
- , fCurrentComplexType(0)
- , fCurrentTypeNameStack(0)
- , fCurrentGroupStack(0)
- , fIC_NamespaceDepth(0)
- , fIC_Elements(0)
- , fDeclStack(0)
- , fGlobalDeclarations(0)
- , fNotationRegistry(0)
- , fRedefineComponents(0)
- , fIdentityConstraintNames(0)
- , fValidSubstitutionGroups(0)
- , fIC_NodeListNS(0)
- , fIC_ElementsNS(0)
- , fIC_NamespaceDepthNS(0)
- , fParser(0)
- , fPreprocessedNodes(0)
- , fLocator(0)
- , fMemoryManager(manager)
- , fAttributeCheck(manager)
- {
- try {
- if (fGrammarResolver && schemaRoot && fURIStringPool) {
- init();
- preprocessSchema(schemaRoot, schemaURL);
- doTraverseSchema(schemaRoot);
- }
- }
- catch(...) {
- cleanUp();
- throw;
- }
- }
- 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);
- fIC_NamespaceDepth = fIC_NamespaceDepthNS->get(fTargetNSURIString);
- unsigned int icListSize = fIC_Elements->size();
- for (unsigned int i=0; i < icListSize; i++) {
- SchemaElementDecl* curElem = fIC_Elements->elementAt(i);
- ValueVectorOf<DOMElement*>* icNodes = fIC_NodeListNS->get(curElem);
- unsigned int icNodesSize = icNodes->size();
- unsigned int scopeDepth = fIC_NamespaceDepth->elementAt(i);
- for (unsigned int j = 0; j < icNodesSize; j++) {
- traverseKeyRef(icNodes->elementAt(j), curElem, scopeDepth);
- }
- }
- }
- fSchemaInfo->setProcessed();
- }
- void TraverseSchema::preprocessSchema(DOMElement* const schemaRoot,
- const XMLCh* const schemaURL) {
- // 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 (fMemoryManager) RefHashTableOf<ComplexTypeInfo>(29, fMemoryManager);
- fSchemaGrammar->setComplexTypeRegistry(fComplexTypeRegistry);
- }
- fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry();
- if (fGroupRegistry == 0 ) {
- fGroupRegistry = new (fMemoryManager) RefHashTableOf<XercesGroupInfo>(13, fMemoryManager);
- fSchemaGrammar->setGroupInfoRegistry(fGroupRegistry);
- }
- fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry();
- if (fAttGroupRegistry == 0 ) {
- fAttGroupRegistry = new (fMemoryManager) RefHashTableOf<XercesAttGroupInfo>(13, fMemoryManager);
- fSchemaGrammar->setAttGroupInfoRegistry(fAttGroupRegistry);
- }
- fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry();
- if (fAttributeDeclRegistry == 0) {
- fAttributeDeclRegistry = new (fMemoryManager) RefHashTableOf<XMLAttDef>(29, fMemoryManager);
- fSchemaGrammar->setAttributeDeclRegistry(fAttributeDeclRegistry);
- }
- fNamespaceScope = fSchemaGrammar->getNamespaceScope();
- if (fNamespaceScope == 0) {
- fNamespaceScope = new (fMemoryManager) NamespaceScope(fMemoryManager);
- fNamespaceScope->reset(fEmptyNamespaceURI);
- fSchemaGrammar->setNamespaceScope(fNamespaceScope);
- }
- fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups();
- if (!fValidSubstitutionGroups) {
- fValidSubstitutionGroups = new (fMemoryManager) RefHash2KeysTableOf<ElemVector>(29, fMemoryManager);
- fSchemaGrammar->setValidSubstitutionGroups(fValidSubstitutionGroups);
- }
- //Retrieve the targetnamespace URI information
- const XMLCh* targetNSURIStr = schemaRoot->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
- fSchemaGrammar->setTargetNamespace(targetNSURIStr);
- fScopeCount = 0;
- fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
- fTargetNSURIString = fSchemaGrammar->getTargetNamespace();
- fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString);
- fGrammarResolver->putGrammar(fTargetNSURIString, fSchemaGrammar);
- fAttributeCheck.setIDRefList(fSchemaGrammar->getIDRefList());
- // Save current schema info
- SchemaInfo* currInfo = new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI, fScopeCount,
- fNamespaceScope->increaseDepth(),
- XMLString::replicate(schemaURL, fMemoryManager),
- fTargetNSURIString, schemaRoot,
- fMemoryManager);
- if (fSchemaInfo) {
- fSchemaInfo->addSchemaInfo(currInfo, SchemaInfo::IMPORT);
- }
- 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 <xsd:schema>
- 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);
- retrieveNamespaceMapping(schemaRoot);
- 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));
- }
- void TraverseSchema::traverseAnnotationDecl(const DOMElement* const annotationElem,
- const bool topLevel) {
- // -----------------------------------------------------------------------
- // Check Attributes
- // -----------------------------------------------------------------------
- fAttributeCheck.checkAttributes(annotationElem, GeneralAttributeCheck::E_Annotation, this, topLevel);
- for (DOMElement* child = XUtil::getFirstChildElement(annotationElem);
- child != 0;
- child = XUtil::getNextSiblingElement(child)) {
- const XMLCh* name = child->getLocalName();
- if (XMLString::equals(name, SchemaSymbols::fgELT_APPINFO)) {
- fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::E_Appinfo, this);
- }
- else if (XMLString::equals(name, SchemaSymbols::fgELT_DOCUMENTATION)) {
- fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::E_Documentation, this);
- }
- else {
- reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAnnotationContent);
- }
- }
- }
- /**
- * Traverse include
- *
- * <include
- * id = ID
- * schemaLocation = anyURI
- * {any attributes with non-schema namespace . . .}>
- * Content: (annotation?)
- * </include>
- */
- void TraverseSchema::preprocessInclude(const DOMElement* const elem) {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- fAttributeCheck.checkAttributes(elem, GeneralAttributeCheck::E_Include, this, true);
- // ------------------------------------------------------------------
- // First, handle any ANNOTATION declaration
- // ------------------------------------------------------------------
- if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected);
- }
- // ------------------------------------------------------------------
- // Get 'schemaLocation' attribute
- // ------------------------------------------------------------------
- const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION);
- if (!schemaLocation || !*schemaLocation) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNoSchemaLocation, SchemaSymbols::fgELT_INCLUDE);
- return;
- }
- // ------------------------------------------------------------------
- // Resolve schema location
- // ------------------------------------------------------------------
- InputSource* srcToFill = resolveSchemaLocation(schemaLocation);
- Janitor<InputSource> janSrc(srcToFill);
- // Nothing to do
- if (!srcToFill) {
- return;
- }
- const XMLCh* includeURL = srcToFill->getSystemId();
- SchemaInfo* includeSchemaInfo = fSchemaInfoList->get(includeURL, fTargetNSURI);
- if (includeSchemaInfo) {
- fSchemaInfo->addSchemaInfo(includeSchemaInfo, SchemaInfo::INCLUDE);
- return;
- }
- // ------------------------------------------------------------------
- // Parse input source
- // ------------------------------------------------------------------
- if (!fParser)
- fParser = new (fMemoryManager) XSDDOMParser;
- fParser->setValidationScheme(XercesDOMParser::Val_Never);
- fParser->setDoNamespaces(true);
- fParser->setUserEntityHandler(fEntityHandler);
- fParser->setUserErrorReporter(fErrorReporter);
- // Should just issue warning if the schema is not found
- const 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, fScopeCount,
- fNamespaceScope->increaseDepth(),
- XMLString::replicate(includeURL, fMemoryManager),
- fTargetNSURIString, root,
- fMemoryManager);
- 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) {
- SchemaInfo* includeInfo = fPreprocessedNodes->get(elem);
- if (includeInfo) {
- SchemaInfo* saveInfo = fSchemaInfo;
- fSchemaInfo = includeInfo;
- processChildren(includeInfo->getRoot());
- fSchemaInfo = saveInfo;
- }
- }
- /**
- * Traverse import
- *
- * <import
- * id = ID
- * namespace = anyURI
- * schemaLocation = anyURI
- * {any attributes with non-schema namespace . . .}>
- * Content: (annotation?)
- * </import>
- */
- void TraverseSchema::preprocessImport(const DOMElement* const elem) {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- fAttributeCheck.checkAttributes(elem, GeneralAttributeCheck::E_Import, this, true);
- // ------------------------------------------------------------------
- // First, handle any ANNOTATION declaration
- // ------------------------------------------------------------------
- if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected);
- }
- // ------------------------------------------------------------------
- // Handle 'namespace' attribute
- // ------------------------------------------------------------------
- const XMLCh* nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE);
- if (XMLString::equals(nameSpace, fTargetNSURIString)) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Import_1_1);
- return;
- }
- if ((!nameSpace || !*nameSpace) && fTargetNSURI == fEmptyNamespaceURI) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Import_1_2);
- return;
- }
- // ------------------------------------------------------------------
- // Resolve namespace to a grammar
- // ------------------------------------------------------------------
- Grammar* aGrammar = (nameSpace) ? fGrammarResolver->getGrammar(nameSpace) : 0;
- bool grammarFound = (aGrammar && (aGrammar->getGrammarType() == Grammar::SchemaGrammarType));
- if (grammarFound) {
- fSchemaInfo->addImportedNS(fURIStringPool->addOrFind(nameSpace));
- }
- // ------------------------------------------------------------------
- // Get 'schemaLocation' attribute
- // ------------------------------------------------------------------
- const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION);
- if (!schemaLocation || !*schemaLocation) {
- return;
- }
- // ------------------------------------------------------------------
- // Resolve schema location
- // ------------------------------------------------------------------
- InputSource* srcToFill = resolveSchemaLocation(schemaLocation);
- Janitor<InputSource> janSrc(srcToFill);
- // Nothing to do
- if (!srcToFill) {
- return;
- }
- const XMLCh* importURL = srcToFill->getSystemId();
- SchemaInfo* importSchemaInfo = 0;
- if (nameSpace)
- importSchemaInfo = fSchemaInfoList->get(importURL, fURIStringPool->addOrFind(nameSpace));
- else
- importSchemaInfo = fSchemaInfoList->get(importURL, fEmptyNamespaceURI);
- if (importSchemaInfo) {
- fSchemaInfo->addSchemaInfo(importSchemaInfo, SchemaInfo::IMPORT);
- return;
- }
- if (grammarFound) {
- return;
- }
- // ------------------------------------------------------------------
- // Parse input source
- // ------------------------------------------------------------------
- if (!fParser)
- fParser = new (fMemoryManager) XSDDOMParser;
- fParser->setValidationScheme(XercesDOMParser::Val_Never);
- fParser->setDoNamespaces(true);
- fParser->setUserEntityHandler(fEntityHandler);
- fParser->setUserErrorReporter(fErrorReporter);
- // Should just issue warning if the schema is not found
- const 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, nameSpace)) {
- reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::ImportNamespaceDifference,
- schemaLocation, targetNSURIString, nameSpace);
- }
- else {
- // --------------------------------------------------------
- // Preprocess new schema
- // --------------------------------------------------------
- SchemaInfo* saveInfo = fSchemaInfo;
- fSchemaGrammar = new (fMemoryManager) SchemaGrammar(fMemoryManager);
- preprocessSchema(root, importURL);
- fPreprocessedNodes->put((void*) elem, fSchemaInfo);
- // --------------------------------------------------------
- // Restore old schema information
- // --------------------------------------------------------
- restoreSchemaInfo(saveInfo, SchemaInfo::IMPORT);
- }
- }
- }
- void TraverseSchema::traverseImport(const DOMElement* const elem) {
- 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
- *
- * <redefine>
- * schemaLocation = uriReference
- * {any attributes with non-schema namespace . . .}>
- * Content: (annotation | (
- * attributeGroup | complexType | group | simpleType))*
- * </redefine>
- */
- void TraverseSchema::preprocessRedefine(const DOMElement* const redefineElem) {
- // ------------------------------------------------------------------
- // 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<XMLCh>(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) {
- 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 <redefine>'s may perhaps be
- // encountered; we leave recursion to sort this out.
- fSchemaInfo = redefinedInfo;
- processChildren(fSchemaInfo->getRoot());
- fSchemaInfo = saveInfo;
- // Now traverse our own <redefine>
- processChildren(redefineElem);
- }
- }
- /**
- * Traverse the Choice, Sequence declaration
- *
- * <choice-sequqnce
- * id = ID
- * maxOccurs = (nonNegativeInteger | unbounded) : 1
- * minOccurs = nonNegativeInteger : 1
- * Content: (annotation?, (element | group | choice | sequence | any)*)
- * </choice-sequence>
- */
- ContentSpecNode*
- TraverseSchema::traverseChoiceSequence(const DOMElement* const elem,
- const int modelGroupType)
- {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- fAttributeCheck.checkAttributes(elem, GeneralAttributeCheck::E_Sequence, this);
- // ------------------------------------------------------------------
- // Process contents
- // ------------------------------------------------------------------
- DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true);
- ContentSpecNode* left = 0;
- ContentSpecNode* right = 0;
- bool hadContent = false;
- for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
- ContentSpecNode* contentSpecNode = 0;
- bool seeParticle = false;
- const XMLCh* childName = child->getLocalName();
- if (XMLString::equals(childName, SchemaSymbols::fgELT_ELEMENT)) {
- QName* eltQName = traverseElementDecl(child);
- if (eltQName == 0) {
- continue;
- }
- contentSpecNode = new (fMemoryManager) ContentSpecNode
- (
- eltQName
- , false
- , fMemoryManager
- );
- seeParticle = true;
- }
- else if (XMLString::equals(childName, SchemaSymbols::fgELT_GROUP)) {
- XercesGroupInfo* grpInfo = traverseGroupDecl(child, false);
- if (!grpInfo) {
- continue;
- }
- contentSpecNode = grpInfo->getContentSpec();
- if (!contentSpecNode) {
- continue;
- }
- if (contentSpecNode->hasAllContent()) {
- reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AllContentLimited);
- continue;
- }
- contentSpecNode = new (fMemoryManager) ContentSpecNode(*contentSpecNode);
- seeParticle = true;
- }
- else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) {
- contentSpecNode = traverseChoiceSequence(child,ContentSpecNode::Choice);
- seeParticle = true;
- }
- else if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) {
- contentSpecNode = traverseChoiceSequence(child,ContentSpecNode::Sequence);
- seeParticle = true;
- }
- else if (XMLString::equals(childName, SchemaSymbols::fgELT_ANY)) {
- contentSpecNode = traverseAny(child);
- seeParticle = true;
- }
- else {
- reportSchemaError(child, XMLUni::fgValidityDomain, XMLValid::GroupContentRestricted, childName);
- }
- if (contentSpecNode) {
- hadContent = true;
- }
- if (seeParticle) {
- checkMinMax(contentSpecNode, child, Not_All_Context);
- }
- if (left == 0) {
- left = contentSpecNode;
- }
- else if (right == 0) {
- right = contentSpecNode;
- }
- else {
- left = new (fMemoryManager) ContentSpecNode
- (
- (ContentSpecNode::NodeTypes) modelGroupType
- , left
- , right
- , true
- , true
- , fMemoryManager
- );
- right = contentSpecNode;
- }
- }
- if (hadContent) {
- left = new (fMemoryManager) ContentSpecNode
- (
- (ContentSpecNode::NodeTypes) modelGroupType
- , left
- , right
- , true
- , true
- , fMemoryManager
- );
- }
- return left;
- }
- /**
- * Traverse SimpleType declaration:
- * <simpleType
- * id = ID
- * name = NCName>
- * Content: (annotation? , ((list | restriction | union)))
- * </simpleType>
- *
- * traverse <list>|<restriction>|<union>
- */
- DatatypeValidator*
- TraverseSchema::traverseSimpleTypeDecl(const DOMElement* const childElem,
- const bool topLevel, int baseRefContext)
- {
- // ------------------------------------------------------------------
- // Process contents
- // ------------------------------------------------------------------
- const XMLCh* name = getElementAttValue(childElem,SchemaSymbols::fgATT_NAME);
- bool nameEmpty = (!name || !*name);
- if (topLevel && nameEmpty) {
- reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
- SchemaSymbols::fgELT_SIMPLETYPE);
- return 0;
- }
- if (nameEmpty) { // anonymous simpleType
- name = genAnonTypeName(fgAnonSNamePrefix);
- }
- else if (!XMLString::isValidNCName(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);
- // 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 (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;
- }
- DatatypeValidator *tmpDV = traverseByList(childElem, content, name, fullName, finalSet);
- if(tmpDV && nameEmpty)
- tmpDV->setAnonymous();
- return tmpDV;
- }
- else if (XMLString::equals(varietyName, SchemaSymbols::fgELT_RESTRICTION)) { //traverse Restriction
- DatatypeValidator *tmpDV = traverseByRestriction(childElem, content, name, fullName, finalSet);
- if(tmpDV && nameEmpty)
- tmpDV->setAnonymous();
- return tmpDV;
- }
- else if (XMLString::equals(varietyName, SchemaSymbols::fgELT_UNION)) { //traverse union
- DatatypeValidator *tmpDV = traverseByUnion(childElem, content, name, fullName, finalSet, baseRefContext);
- if(tmpDV && nameEmpty)
- tmpDV->setAnonymous();
- return tmpDV;
- }
- else {
- reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::FeatureUnsupported, varietyName);
- popCurrentTypeNameStack();
- }
- }
- return dv;
- }
- /**
- * Traverse ComplexType Declaration - CR Implementation.
- *
- * <complexType
- * abstract = boolean
- * block = #all or (possibly empty) subset of {extension, restriction}
- * final = #all or (possibly empty) subset of {extension, restriction}
- * id = ID
- * mixed = boolean : false
- * name = NCName>
- * Content: (annotation? , (simpleContent | complexContent |
- * ( (group | all | choice | sequence)? ,
- * ( (attribute | attributeGroup)* , anyAttribute?))))
- * </complexType>
- */
- int TraverseSchema::traverseComplexTypeDecl(const DOMElement* const elem,
- const bool topLevel,
- const XMLCh* const recursingTypeName) {
- // Get the attributes of the complexType
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- 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 (!XMLString::isValidNCName(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
- // -----------------------------------------------------------------------
- unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_ComplexTypeGlobal
- : GeneralAttributeCheck::E_ComplexTypeLocal;
- fAttributeCheck.checkAttributes(elem, scope, this, topLevel);
- // -----------------------------------------------------------------------
- // Create a new instance
- // -----------------------------------------------------------------------
- bool preProcessFlag = (typeInfo) ? typeInfo->getPreprocessed() : false;
- unsigned int previousCircularCheckIndex = fCircularCheckIndex;
- int previousScope = fCurrentScope;
- if (preProcessFlag) {
- fCurrentScope = typeInfo->getScopeDefined();
- typeInfo->setPreprocessed(false);
- }
- else {
- // ------------------------------------------------------------------
- // Register the type
- // ------------------------------------------------------------------
- typeInfo = new (fMemoryManager) ComplexTypeInfo(fMemoryManager);
- if(isAnonymous) {
- typeInfo->setAnonymous();
- }
- fCurrentScope = fScopeCount++;
- fComplexTypeRegistry->put((void*) fullName, typeInfo);
- typeInfo->setTypeName(fullName);
- typeInfo->setScopeDefined(fCurrentScope);
- if (fFullConstraintChecking) {
- XSDLocator* aLocator = new (fMemoryManager) 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);
- // ------------------------------------------------------------------
- // Process the content of the complex type declaration
- // ------------------------------------------------------------------
- try {
- const XMLCh* mixedVal = getElementAttValue(elem,SchemaSymbols::fgATT_MIXED);
- 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,0,0, isMixed);
- }
- else {
- const XMLCh* childName = child->getLocalName();
- if (XMLString::equals(childName, SchemaSymbols::fgELT_SIMPLECONTENT)) {
- // SIMPLE CONTENT element
- traverseSimpleContentDecl(name, fullName, child, typeInfo);
- 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);
- 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, 0, 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);
- 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);
- }
- }
- // ------------------------------------------------------------------
- // Before exiting, restore the scope, mainly for nested anonymous types
- // ------------------------------------------------------------------
- popCurrentTypeNameStack();
- fCircularCheckIndex = previousCircularCheckIndex;
- fCurrentScope = previousScope;
- fCurrentComplexType = saveTypeInfo;
- return typeNameIndex;
- }
- /**
- * Traverse Group Declaration.
- *
- * <group
- * id = ID
- * maxOccurs = string
- * minOccurs = nonNegativeInteger
- * name = NCName
- * ref = QName>
- * Content: (annotation? , (all | choice | sequence)?)
- * <group/>
- *
- */
- XercesGroupInfo*
- TraverseSchema::traverseGroupDecl(const DOMElement* const elem,
- const bool topLevel) {
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
- 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);
- // ------------------------------------------------------------------
- // Check for annotations
- // ------------------------------------------------------------------
- DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true);
- // ------------------------------------------------------------------
- // Handle "ref="
- // ------------------------------------------------------------------
- if (!topLevel) {
- if (refEmpty) {
- return 0;
- }
- return processGroupRef(elem, ref);
- }
- // ------------------------------------------------------------------
- // Process contents of global groups
- // ------------------------------------------------------------------
- // name must be a valid NCName
- if (!XMLString::isValidNCName(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;
- }
- int saveScope = fCurrentScope;
- ContentSpecNode* specNode = 0;
- XercesGroupInfo* saveGroupInfo = fCurrentGroupInfo;
- groupInfo = new (fMemoryManager) XercesGroupInfo(fMemoryManager);
- fCurrentGroupStack->addElement(nameIndex);
- fCurrentGroupInfo = groupInfo;
- if (fCurrentScope == Grammar::TOP_LEVEL_SCOPE) {
- 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();
- if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) {
- specNode = traverseChoiceSequence(content, ContentSpecNode::Sequence);
- }
- else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) {
- specNode = traverseChoiceSequence(content, ContentSpecNode::Choice);
- }
- else if (XMLString::equals(childName, SchemaSymbols::fgELT_ALL)) {
- specNode = traverseAll(content);
- }
- else {
- illegalChild = true;
- }
- if (illegalChild || XUtil::getNextSiblingElement(content) != 0) {
- reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::GroupContentError, name);
- }
- }
- // ------------------------------------------------------------------
- // Set groupInfo and pop group name from stack
- // ------------------------------------------------------------------
- unsigned int stackSize = fCurrentGroupStack->size();
- if (stackSize != 0) {
- fCurrentGroupStack->removeElementAt(stackSize - 1);
- }
- fCurrentGroupInfo->setContentSpec(specNode);
- fGroupRegistry->put((void*) fullName, fCurrentGroupInfo);
- fCurrentGroupInfo = saveGroupInfo;
- fCurrentScope = saveScope;
- if (fFullConstraintChecking) {
- XSDLocator* aLocator = new (fMemoryManager) XSDLocator();
- groupInfo->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);
- groupInfo->setBaseGroup(fGroupRegistry->get(fBuffer.getRawBuffer()));
- }
- }
- return groupInfo;
- }
- /**
- * Traverse attributeGroup Declaration.
- *
- * <attributeGroup
- * id = ID
- * name = NCName
- * ref = QName>
- * Content: (annotation? , (attribute|attributeGroup)*, anyAttribute?)
- * <attributeGroup/>
- *
- */
- XercesAttGroupInfo*
- TraverseSchema::traverseAttributeGroupDecl(const DOMElement* const elem,
- ComplexTypeInfo* const typeInfo,
- const bool topLevel) {
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
- 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);
- // ------------------------------------------------------------------
- // Handle "ref="
- // ------------------------------------------------------------------
- if (!topLevel) {
- if (refEmpty) {
- return 0;
- }
- return processAttributeGroupRef(elem, ref, typeInfo);
- }
- // ------------------------------------------------------------------
- // Handle "name="
- // ------------------------------------------------------------------
- // name must be a valid NCName
- if (!XMLString::isValidNCName(name)) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
- SchemaSymbols::fgELT_ATTRIBUTEGROUP, name);
- return 0;
- }
- // ------------------------------------------------------------------
- // Check for annotations
- // ------------------------------------------------------------------
- DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true);
- // ------------------------------------------------------------------
- // Process contents of global attributeGroups
- // ------------------------------------------------------------------
- XercesAttGroupInfo* saveAttGroupInfo = fCurrentAttGroupInfo;
- XercesAttGroupInfo* attGroupInfo = new (fMemoryManager) XercesAttGroupInfo(fMemoryManager);
- fDeclStack->addElement(elem);
- fCurrentAttGroupInfo = attGroupInfo;
- 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);
- // ------------------------------------------------------------------
- // Restore old attGroupInfo
- // ------------------------------------------------------------------
- fAttGroupRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), attGroupInfo);
- 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);
- }
- }
- return attGroupInfo;
- }
- inline XercesAttGroupInfo*
- TraverseSchema::traverseAttributeGroupDeclNS(const DOMElement* const elem,
- const XMLCh* const uriStr,
- const XMLCh* const name) {
- // ------------------------------------------------------------------
- // 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
- *
- * <any
- * id = ID
- * maxOccurs = (nonNegativeInteger | unbounded) : 1
- * minOccurs = nonNegativeInteger : 1
- * namespace = ((##any | ##other) | List of (anyURI |
- * (##targetNamespace | ##local)) ) : ##any
- * processContents = (lax | skip | strict) : strict
- * {any attributes with non-schema namespace . . .}>
- * Content: (annotation?)
- * </any>
- */
- ContentSpecNode*
- TraverseSchema::traverseAny(const DOMElement* const elem) {
- // -----------------------------------------------------------------------
- // Check Attributes
- // -----------------------------------------------------------------------
- fAttributeCheck.checkAttributes(elem, GeneralAttributeCheck::E_Any, this);
- // ------------------------------------------------------------------
- // First, handle any ANNOTATION declaration
- // ------------------------------------------------------------------
- if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected);
- }
- // ------------------------------------------------------------------
- // 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, fgStrict)) {
- if (XMLString::equals(processContents, fgLax)) {
- anyType = ContentSpecNode::Any_Lax;
- anyOtherType = ContentSpecNode::Any_Other_Lax;
- anyLocalType = ContentSpecNode::Any_NS_Lax;
- }
- else if (XMLString::equals(processContents, fgSkip)) {
- 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 (fMemoryManager) ContentSpecNode
- (
- new (fMemoryManager) QName
- (
- XMLUni::fgZeroLenString
- , XMLUni::fgZeroLenString
- , fEmptyNamespaceURI
- , fMemoryManager
- )
- , false
- , fMemoryManager
- );
- retSpecNode->setType(anyType);
- }
- else if (XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER)) {
- retSpecNode = new (fMemoryManager) ContentSpecNode
- (
- new (fMemoryManager) QName
- (
- XMLUni::fgZeroLenString
- , XMLUni::fgZeroLenString
- , fTargetNSURI, fMemoryManager
- )
- , false
- , fMemoryManager
- );
- retSpecNode->setType(anyOtherType);
- }
- else {
- BaseRefVectorOf<XMLCh>* nameSpaceTokens = XMLString::tokenizeString(nameSpace);
- ValueVectorOf<unsigned int> uriList(8, fMemoryManager);
- ContentSpecNode* firstNode = 0;
- ContentSpecNode* secondNode = 0;
- unsigned int tokensSize = nameSpaceTokens->size();
- DatatypeValidator* anyURIDV = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYURI);
- for (unsigned int i=0; i < tokensSize; i++) {
- const XMLCh* tokenElem = nameSpaceTokens->elementAt(i);
- 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);
- }
- catch(const XMLException& excep) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DisplayErrorMessage, excep.getMessage());
- }
- uriIndex = fURIStringPool->addOrFind(tokenElem);
- }
- }
- if (uriList.containsElement(uriIndex)) {
- continue;
- }
- uriList.addElement(uriIndex);
- firstNode = new (fMemoryManager) ContentSpecNode
- (
- new (fMemoryManager) QName
- (
- XMLUni::fgZeroLenString
- , XMLUni::fgZeroLenString
- , uriIndex, fMemoryManager
- )
- , false
- , fMemoryManager
- );
- firstNode->setType(anyLocalType);
- if (secondNode == 0) {
- secondNode = firstNode;
- }
- else {
- secondNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::Choice
- , secondNode
- , firstNode
- , true
- , true
- , fMemoryManager
- );
- }
- }
- retSpecNode = secondNode;
- delete nameSpaceTokens;
- }
- return retSpecNode;
- }
- /**
- * Traverse all
- *
- * <all
- * id = ID
- * maxOccurs = 1 : 1
- * minOccurs = (0 | 1) : 1
- * {any attributes with non-schema namespace . . .}>
- * Content: (annotation?, element*)
- * </all>
- */
- ContentSpecNode*
- TraverseSchema::traverseAll(const DOMElement* const elem) {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- fAttributeCheck.checkAttributes(elem, GeneralAttributeCheck::E_All, this);
- // ------------------------------------------------------------------
- // Process contents
- // ------------------------------------------------------------------
- DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true);
- if (child == 0) {
- return 0;
- }
- ContentSpecNode* left = 0;
- ContentSpecNode* right = 0;
- bool hadContent = false;
- for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
- ContentSpecNode* contentSpecNode = 0;
- const XMLCh* childName = child->getLocalName();
- if (XMLString::equals(childName, SchemaSymbols::fgELT_ELEMENT)) {
- QName* eltQName = traverseElementDecl(child);
- if (eltQName == 0) {
- continue;
- }
- contentSpecNode = new (fMemoryManager) ContentSpecNode
- (
- eltQName
- , false
- , fMemoryManager
- );
- checkMinMax(contentSpecNode, child, All_Element);
- }
- else {
- reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AllContentError, childName);
- continue;
- }
- hadContent = true;
- if (!left) {
- left = contentSpecNode;
- }
- else if (!right) {
- right = contentSpecNode;
- }
- else {
- left = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::All
- , left
- , right
- , true
- , true
- , fMemoryManager
- );
- right = contentSpecNode;
- }
- }
- if (hadContent) {
- left = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::All
- , left
- , right
- , true
- , true
- , fMemoryManager
- );
- }
- return left;
- }
- /**
- * Traverses Schema attribute declaration.
- *
- * <attribute
- * fixed = string
- * default = string
- * form = qualified | unqualified
- * id = ID
- * name = NCName
- * ref = QName
- * type = QName
- * use = optional | prohibited | required : optional
- >
- * Content: (annotation? , simpleType?)
- * <attribute/>
- *
- * @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) {
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
- 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);
- 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);
- DOMElement* simpleType = checkContent(elem, XUtil::getFirstChildElement(elem), true);
- 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) ? SchemaSymbols::fgATT_NAME : SchemaSymbols::fgATT_REF,
- (name) ? name : ref);
- }
- if (defaultVal) {
- if (fixedVal) {
- fixedVal = 0;
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeDefaultFixedValue);
- }
- if ((useVal && *useVal)
- && !XMLString::equals(useVal, SchemaSymbols::fgATTVAL_OPTIONAL)) {
- useVal = 0;
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotOptionalDefaultAttValue);
- }
- }
- // 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);
- }
- processAttributeDeclRef(elem, typeInfo, ref, useVal, defaultVal, fixedVal);
- return;
- }
- // processing 'name'
- if (!XMLString::isValidNCName(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);
- }
- 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) {
- try {
- dv->validate(valueToCheck);
- }
- catch (const XMLException& excep) {
- reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DisplayErrorMessage, excep.getMessage());
- }
- catch(...) {
- reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueToCheck);
- }
- }
- if (ofTypeID && valueToCheck) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3,
- SchemaSymbols::fgATT_NAME, 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 (fMemoryManager) SchemaAttDef
- (
- XMLUni::fgZeroLenString
- , name
- , uriIndex
- , attType
- , XMLAttDef::Implied
- , fMemoryManager
- );
- 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 (topLevel) {
- fAttributeDeclRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), attDef);
- }
- else {
-
- bool toClone = false;
- if (typeInfo) {
- toClone = true;
- typeInfo->addAttDef(attDef);
- }
- if (fCurrentAttGroupInfo) {
- fCurrentAttGroupInfo->addAttDef(attDef, toClone);
- }
- }
- }
- /**
- * Traverses Schema element declaration.
- *
- * <element
- * abstract = boolean : false
- * block = (#all | List of (substitution | extension | restriction
- * | list | union))
- * default = string
- * final = (#all | List of (extension | restriction))
- * fixed = string
- * form = (qualified | unqualified)
- * id = ID
- * maxOccurs = (nonNegativeInteger | unbounded) : 1
- * minOccurs = nonNegativeInteger : 1
- * name = NCName
- * nillable = boolean : false
- * ref = QName
- * substitutionGroup = QName
- * type = QName
- * Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
- * </element>
- *
- * @param elem: the declaration of the element under consideration
- */
- QName* TraverseSchema::traverseElementDecl(const DOMElement* const elem,
- const bool topLevel) {
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
- bool nameEmpty = (!name || !*name) ? true : false;
- bool refEmpty = (!ref || !*ref) ? true : false;
- if (nameEmpty && topLevel) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::GlobalNoNameElement);
- return 0;
- }
- if (nameEmpty && refEmpty) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefElement);
- return 0;
- }
- if (topLevel) {
- if (fSchemaGrammar->getElemDecl(fTargetNSURI, name, 0, Grammar::TOP_LEVEL_SCOPE) != 0) {
- return new (fMemoryManager) QName(name, fTargetNSURI, fMemoryManager);
- }
- }
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_ElementGlobal
- : (refEmpty) ? GeneralAttributeCheck::E_ElementLocal
- : GeneralAttributeCheck::E_ElementRef;
- fAttributeCheck.checkAttributes(elem, scope, this, topLevel);
- // ------------------------------------------------------------------
- // Process contents
- // ------------------------------------------------------------------
- const XMLCh* fixed = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED);
- const XMLCh* deflt = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT);
- if((fixed && *fixed) && (deflt && *deflt)) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::ElementWithFixedAndDefault);
- }
- if (nameEmpty || (!refEmpty && !topLevel)) {
- if (!nameEmpty) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationWithNameRef,
- SchemaSymbols::fgELT_ELEMENT, name);
- }
- if (!isValidRefDeclaration(elem)) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::BadAttWithRef);
- }
- return processElementDeclRef(elem, ref);
- }
- // Name is notEmpty
- if (!XMLString::isValidNCName(name)) {
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
- SchemaSymbols::fgELT_ELEMENT, name);
- return 0;
- }
- const XMLCh* anotherSchemaURI = 0;
- int scopeDefined = Grammar::UNKNOWN_SCOPE;
- bool noErrorFound = true;
- bool anonymousType = false;
- DatatypeValidator* validator = 0;
- DatatypeValidator* subGroupValidator = 0;
- ComplexTypeInfo* typeInfo = 0;
- ComplexTypeInfo* subGroupTypeInfo = 0;
- ContentSpecNode* contentSpecNode = 0;
- SchemaElementDecl::ModelTypes contentSpecType = SchemaElementDecl::Any;
- // Create element decl
- bool isDuplicate = false;
- SchemaElementDecl* elemDecl =
- createSchemaElementDecl(elem, topLevel, contentSpecType, isDuplicate, (fixed != 0));
- if (elemDecl == 0) {
- return 0;
- }
- if (!isDuplicate) {
- fSchemaGrammar->putElemDecl(elemDecl);
- if (fCurrentGroupInfo &&
- elemDecl->getEnclosingScope() == fCurrentGroupInfo->getScope()) {
- fCurrentGroupInfo->addElement(elemDecl);
- }
- if (fCurrentComplexType &&
- elemDecl->getEnclosingScope() == fCurrentComplexType->getScopeDefined()) {
- fCurrentComplexType->addElement(elemDecl);
- }
- }
- // Resolve the type for the element
- const DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true);
- 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) {
- noErrorFound = false;
- }
- else if (!isDuplicate) {
- typeInfo->setElementId(elemDecl->getId());
- //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);
- }
- if (!validator) {
- noErrorFound = false;
- }
- contentSpecType = SchemaElementDecl::Simple;
- 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);
- if (typeStr && *typeStr) {
- if (anonymousType) {
- noErrorFound = false;
- reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::ElementWithTypeAndAnonType, name);
- }
- else {
- 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);
- anotherSchemaURI = checkTypeFromAnotherSchema(elem, typeStr);
- // get complex type info
- typeInfo = getElementComplexTypeInfo(elem, typeStr, noErrorFound, anotherSchemaURI);
- // get simple type validtor - if not a complex type