TraverseSchema.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:304k
源码类别:
xml/soap/webservice
开发平台:
C/C++
- /*
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 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.70 2001/12/06 17:50:52 tng Exp $
- */
- // ---------------------------------------------------------------------------
- // Includes
- // ---------------------------------------------------------------------------
- #include <validators/schema/TraverseSchema.hpp>
- #include <sax/EntityResolver.hpp>
- #include <validators/schema/identity/IC_Key.hpp>
- #include <validators/schema/identity/IC_KeyRef.hpp>
- #include <validators/schema/identity/IC_Unique.hpp>
- #include <validators/schema/identity/IC_Field.hpp>
- #include <validators/schema/identity/IC_Selector.hpp>
- #include <validators/schema/identity/XercesXPath.hpp>
- #include <validators/datatype/DatatypeValidatorFactory.hpp>
- #include <util/XMLStringTokenizer.hpp>
- #include <validators/schema/XUtil.hpp>
- #include <validators/common/GrammarResolver.hpp>
- #include <validators/schema/SchemaGrammar.hpp>
- #include <validators/schema/SchemaAttDef.hpp>
- #include <internal/XMLReader.hpp>
- #include <validators/schema/ComplexTypeInfo.hpp>
- #include <validators/schema/NamespaceScope.hpp>
- #include <validators/schema/SchemaAttDefList.hpp>
- #include <internal/XMLScanner.hpp>
- #include <internal/XMLInternalErrorHandler.hpp>
- #include <framework/LocalFileInputSource.hpp>
- #include <framework/URLInputSource.hpp>
- #include <parsers/DOMParser.hpp>
- #include <validators/schema/identity/XPathException.hpp>
- #include <validators/schema/GeneralAttributeCheck.hpp>
- #include <validators/schema/XercesGroupInfo.hpp>
- #include <validators/schema/XercesAttGroupInfo.hpp>
- #include <util/HashPtr.hpp>
- // ---------------------------------------------------------------------------
- // 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
- };
- // ---------------------------------------------------------------------------
- // TraverseSchema: Constructors and Destructor
- // ---------------------------------------------------------------------------
- TraverseSchema::TraverseSchema( const DOM_Element& schemaRoot
- , XMLStringPool* const uriStringPool
- , SchemaGrammar* const schemaGrammar
- , GrammarResolver* const grammarResolver
- , XMLScanner* const xmlScanner
- , XMLValidator* const xmlValidator
- , const XMLCh* const schemaURL
- , EntityResolver* const entityResolver
- , ErrorHandler* const errorHandler)
- : fFullConstraintChecking(false)
- , fElemAttrDefaultQualified(0)
- , fTargetNSURI(-1)
- , fEmptyNamespaceURI(-1)
- , fCurrentScope(Grammar::TOP_LEVEL_SCOPE)
- , fAnonXSTypeCount(0)
- , fFinalDefault(0)
- , fBlockDefault(0)
- , fScopeCount(0)
- , fTargetNSURIString(0)
- , fDatatypeRegistry(0)
- , fGrammarResolver(grammarResolver)
- , fSchemaGrammar(schemaGrammar)
- , fEntityResolver(entityResolver)
- , fErrorHandler(errorHandler)
- , fURIStringPool(uriStringPool)
- , fStringPool(0)
- , fValidator(xmlValidator)
- , 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)
- , fGlobalDeclarations(0)
- , fNotationRegistry(0)
- , fRedefineComponents(0)
- , fIdentityConstraintNames(0)
- , fSubstitutionGroups(0)
- , fValidSubstitutionGroups(0)
- , fRefElements(0)
- , fRefElemScope(0)
- , fIC_NodeListNS(0)
- , fIC_ElementsNS(0)
- , fIC_NamespaceDepthNS(0)
- {
- try {
- if (fGrammarResolver && !schemaRoot.isNull()) {
- init();
- doTraverseSchema(schemaRoot, schemaURL);
- }
- }
- catch(...) {
- cleanUp();
- throw;
- }
- }
- TraverseSchema::~TraverseSchema()
- {
- cleanUp();
- }
- // ---------------------------------------------------------------------------
- // TraverseSchema: Traversal methods
- // ---------------------------------------------------------------------------
- void TraverseSchema::doTraverseSchema(const DOM_Element& schemaRoot,
- const XMLCh* const schemaURL) {
- // Make sure namespace binding is defaulted
- DOM_Element rootElem = schemaRoot;
- DOMString rootPrefix = schemaRoot.getPrefix();
- if (rootPrefix == 0 || rootPrefix.length() == 0) {
- DOMString xmlns = rootElem.getAttribute(XMLUni::fgXMLNSString);
- if (xmlns.length() == 0) {
- rootElem.setAttribute(XMLUni::fgXMLNSString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
- }
- }
- if (fFullConstraintChecking) {
- fRefElements = new RefVectorOf<QName>(32);
- fRefElemScope = new ValueVectorOf<int>(32);
- }
- // 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 RefHashTableOf<ComplexTypeInfo>(29);
- fSchemaGrammar->setComplexTypeRegistry(fComplexTypeRegistry);
- }
- fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry();
- if (fGroupRegistry == 0 ) {
- fGroupRegistry = new RefHashTableOf<XercesGroupInfo>(13);
- fSchemaGrammar->setGroupInfoRegistry(fGroupRegistry);
- }
- fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry();
- if (fAttGroupRegistry == 0 ) {
- fAttGroupRegistry = new RefHashTableOf<XercesAttGroupInfo>(13);
- fSchemaGrammar->setAttGroupInfoRegistry(fAttGroupRegistry);
- }
- fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry();
- if (fAttributeDeclRegistry == 0) {
- fAttributeDeclRegistry = new RefHashTableOf<XMLAttDef>(29);
- fSchemaGrammar->setAttributeDeclRegistry(fAttributeDeclRegistry);
- }
- fNamespaceScope = fSchemaGrammar->getNamespaceScope();
- if (fNamespaceScope == 0) {
- fNamespaceScope = new NamespaceScope();
- fNamespaceScope->reset(fEmptyNamespaceURI);
- fSchemaGrammar->setNamespaceScope(fNamespaceScope);
- }
- unsigned int namespaceDepth = fNamespaceScope->increaseDepth();
- fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups();
- if (!fValidSubstitutionGroups) {
- fValidSubstitutionGroups = new RefHash2KeysTableOf<ElemVector>(29);
- fSchemaGrammar->setValidSubstitutionGroups(fValidSubstitutionGroups);
- }
- //Retrieve the targetnamespace URI information
- DOMString targetNSURIStr = schemaRoot.getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
- if (targetNSURIStr == 0) {
- fSchemaGrammar->setTargetNamespace(XMLUni::fgZeroLenString);
- }
- else {
- fBuffer.set(targetNSURIStr.rawBuffer(), targetNSURIStr.length());
- fSchemaGrammar->setTargetNamespace(fBuffer.getRawBuffer());
- }
- fTargetNSURIString = fSchemaGrammar->getTargetNamespace();
- fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString);
- fGrammarResolver->putGrammar(fTargetNSURIString, fSchemaGrammar);
- fAttributeCheck.setIDRefList(fSchemaGrammar->getIDRefList());
- traverseSchemaHeader(rootElem);
- // Save current schema info
- SchemaInfo* currInfo = new SchemaInfo(fElemAttrDefaultQualified, fBlockDefault,
- fFinalDefault, fTargetNSURI, fCurrentScope,
- fScopeCount, namespaceDepth,
- XMLString::replicate(schemaURL),
- fTargetNSURIString, fStringPool, schemaRoot);
- if (fSchemaInfo) {
- fSchemaInfo->addSchemaInfo(currInfo, SchemaInfo::IMPORT);
- }
- fSchemaInfo = currInfo;
- fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), fSchemaInfo->getTargetNSURI(), fSchemaInfo);
- // process children nodes
- fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
- fScopeCount = 0;
- 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<DOM_Element>* 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);
- }
- }
- }
- // Element consistency checks - substitution groups
- if (fFullConstraintChecking) {
- checkRefElementConsistency();
- checkParticleDerivation();
- }
- }
- void TraverseSchema::traverseSchemaHeader(const DOM_Element& schemaRoot) {
- // -----------------------------------------------------------------------
- // Check Attributes
- // -----------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::GlobalContext;
- fAttributeCheck.checkAttributes(schemaRoot, scope, this);
- retrieveNamespaceMapping(schemaRoot);
- fElemAttrDefaultQualified = 0;
- if (schemaRoot.getAttribute(SchemaSymbols::fgATT_ELEMENTFORMDEFAULT).equals(SchemaSymbols::fgATTVAL_QUALIFIED)) {
- fElemAttrDefaultQualified |= Elem_Def_Qualified;
- }
- if (schemaRoot.getAttribute(SchemaSymbols::fgATT_ATTRIBUTEFORMDEFAULT).equals(SchemaSymbols::fgATTVAL_QUALIFIED)) {
- fElemAttrDefaultQualified |= Attr_Def_Qualified;
- }
- // Get finalDefault/blockDefault values
- const XMLCh* defaultVal = getElementAttValue(schemaRoot, SchemaSymbols::fgATT_BLOCKDEFAULT);
- const XMLCh* finalVal = getElementAttValue(schemaRoot, SchemaSymbols::fgATT_FINALDEFAULT);
- fBlockDefault = parseBlockSet(defaultVal, ES_Block);
- fFinalDefault = parseFinalSet(finalVal, ECS_Final);
- }
- void TraverseSchema::traverseAnnotationDecl(const DOM_Element& annotationElem) {
- // -----------------------------------------------------------------------
- // Check Attributes
- // -----------------------------------------------------------------------
- bool topLevel = isTopLevelComponent(annotationElem);
- int scope = (topLevel) ? GeneralAttributeCheck::GlobalContext
- : GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(annotationElem, scope, this);
- for (DOM_Element child = XUtil::getFirstChildElement(annotationElem);
- child != 0;
- child = XUtil::getNextSiblingElement(child)) {
- DOMString name = child.getLocalName();
- if (!name.equals(SchemaSymbols::fgELT_APPINFO) &&
- !name.equals(SchemaSymbols::fgELT_DOCUMENTATION)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, 0, 0); //"an <annotation> can only contain <appinfo> and <documentation> elements"
- }
- // General Attribute Checking
- fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::LocalContext, this);
- }
- }
- /**
- * Traverse include
- *
- * <include
- * id = ID
- * schemaLocation = anyURI
- * {any attributes with non-schema namespace . . .}>
- * Content: (annotation?)
- * </include>
- */
- void TraverseSchema::traverseInclude(const DOM_Element& elem) {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::GlobalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // ------------------------------------------------------------------
- // First, handle any ANNOTATION declaration
- // ------------------------------------------------------------------
- if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected);
- }
- // ------------------------------------------------------------------
- // Get 'schemaLocation' attribute
- // ------------------------------------------------------------------
- const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION);
- if (XMLString::stringLen(schemaLocation) == 0) {
- reportSchemaError(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
- // ------------------------------------------------------------------
- DOMParser parser;
- XMLInternalErrorHandler internalErrorHandler(fErrorHandler);
- parser.setValidationScheme(DOMParser::Val_Never);
- parser.setDoNamespaces(true);
- parser.setErrorHandler((ErrorHandler*) &internalErrorHandler);
- parser.setEntityResolver(fEntityResolver);
- // Should just issue warning if the schema is not found
- const bool flag = srcToFill->getIssueFatalErrorIfNotFound();
- srcToFill->setIssueFatalErrorIfNotFound(false);
- parser.parse(*srcToFill) ;
- // Reset the InputSource
- srcToFill->setIssueFatalErrorIfNotFound(flag);
- if (internalErrorHandler.getSawFatal() && fScanner->getExitOnFirstFatal())
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError);
- // ------------------------------------------------------------------
- // Get root element
- // ------------------------------------------------------------------
- DOM_Document document = parser.getDocument();
- if (!document.isNull()) {
- DOM_Element root = document.getDocumentElement();
- if (!root.isNull()) {
- const XMLCh* targetNSURIString = getTargetNamespaceString(root);
- unsigned int targetNSLength = XMLString::stringLen(targetNSURIString);
- // check to see if targetNameSpace is right
- if (targetNSLength != 0
- && XMLString::compareString(targetNSURIString,fTargetNSURIString) != 0){
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::IncludeNamespaceDifference,
- schemaLocation, targetNSURIString);
- return;
- }
- // if targetNamespace is empty, change it to includ'g schema
- // targetNamespace
- if (targetNSLength == 0 && root.getAttributeNode(XMLUni::fgXMLNSString) == 0
- && fTargetNSURI != fEmptyNamespaceURI) {
- root.setAttribute(XMLUni::fgXMLNSString, fTargetNSURIString);
- }
- // --------------------------------------------------------
- // Update schema information with included schema
- // --------------------------------------------------------
- unsigned int namespaceDepth = fNamespaceScope->increaseDepth();
- fElemAttrDefaultQualified = 0;
- traverseSchemaHeader(root);
- // and now we'd better save this stuff!
- SchemaInfo* saveInfo = fSchemaInfo;
- fSchemaInfo = new SchemaInfo(fElemAttrDefaultQualified, fBlockDefault,
- fFinalDefault, fTargetNSURI, fCurrentScope,
- fScopeCount, namespaceDepth,
- XMLString::replicate(includeURL),
- fTargetNSURIString, fStringPool, root);
- fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), fSchemaInfo->getTargetNSURI(), fSchemaInfo);
- saveInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE);
- processChildren(root);
- // --------------------------------------------------------
- // Restore old schema information
- // --------------------------------------------------------
- restoreSchemaInfo(saveInfo);
- }
- }
- }
- /**
- * Traverse import
- *
- * <import
- * id = ID
- * namespace = anyURI
- * schemaLocation = anyURI
- * {any attributes with non-schema namespace . . .}>
- * Content: (annotation?)
- * </import>
- */
- void TraverseSchema::traverseImport(const DOM_Element& elem) {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::GlobalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // ------------------------------------------------------------------
- // First, handle any ANNOTATION declaration
- // ------------------------------------------------------------------
- if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected);
- }
- // ------------------------------------------------------------------
- // Handle 'namespace' attribute
- // ------------------------------------------------------------------
- const XMLCh* nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE);
- if (!XMLString::compareString(nameSpace, fTargetNSURIString)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::Import_1_1);
- return;
- }
- if (!XMLString::stringLen(nameSpace) && fTargetNSURI == fEmptyNamespaceURI) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::Import_1_2);
- return;
- }
- // ------------------------------------------------------------------
- // Get 'schemaLocation' attribute
- // ------------------------------------------------------------------
- const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION);
- if (XMLString::stringLen(schemaLocation) == 0) {
- 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;
- }
- SchemaGrammar* importedGrammar = 0;
- if (nameSpace) {
- Grammar* aGrammar = fGrammarResolver->getGrammar(nameSpace);
- if (aGrammar) {
- if (aGrammar->getGrammarType() == Grammar::SchemaGrammarType) {
- importedGrammar = (SchemaGrammar*) aGrammar;
- return;
- }
- else { // empty string namespace
- //REVISIT
- }
- }
- }
- // ------------------------------------------------------------------
- // Parse input source
- // ------------------------------------------------------------------
- DOMParser parser;
- XMLInternalErrorHandler internalErrorHandler(fErrorHandler);
- parser.setValidationScheme(DOMParser::Val_Never);
- parser.setDoNamespaces(true);
- parser.setErrorHandler((ErrorHandler*) &internalErrorHandler);
- parser.setEntityResolver(fEntityResolver);
- // Should just issue warning if the schema is not found
- const bool flag = srcToFill->getIssueFatalErrorIfNotFound();
- srcToFill->setIssueFatalErrorIfNotFound(false);
- parser.parse(*srcToFill) ;
- // Reset the InputSource
- srcToFill->setIssueFatalErrorIfNotFound(flag);
- if (internalErrorHandler.getSawFatal() && fScanner->getExitOnFirstFatal())
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError);
- // ------------------------------------------------------------------
- // Get root element
- // ------------------------------------------------------------------
- DOM_Document document = parser.getDocument();
- if (!document.isNull()) {
- DOM_Element root = document.getDocumentElement();
- if (root.isNull()) {
- return;
- }
- const XMLCh* targetNSURIString = getTargetNamespaceString(root);
- if (XMLString::compareString(targetNSURIString, nameSpace) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ImportNamespaceDifference,
- schemaLocation, targetNSURIString, nameSpace);
- }
- else {
- // --------------------------------------------------------
- // Traverse new schema
- // --------------------------------------------------------
- SchemaInfo* saveInfo = fSchemaInfo;
- fSchemaGrammar = new SchemaGrammar();
- Janitor<RefVectorOf<QName> > janElem(fRefElements);
- Janitor<ValueVectorOf<int> > janElemScope(fRefElemScope);
- doTraverseSchema(root, importURL);
- // --------------------------------------------------------
- // Restore old schema information
- // --------------------------------------------------------
- restoreSchemaInfo(saveInfo, SchemaInfo::IMPORT);
- // reset fRefElements && fRefElemScope
- if (fFullConstraintChecking) {
- RefVectorOf<QName>* tmpElems = fRefElements;
- ValueVectorOf<int>* tmpElemScope = fRefElemScope;
- fRefElements = janElem.release();
- fRefElemScope = janElemScope.release();
- janElem.reset(tmpElems);
- janElemScope.reset(tmpElemScope);
- }
- }
- }
- }
- /**
- * Traverse redefine declaration
- *
- * <redefine>
- * schemaLocation = uriReference
- * {any attributes with non-schema namespace . . .}>
- * Content: (annotation | (
- * attributeGroup | complexType | group | simpleType))*
- * </redefine>
- */
- void TraverseSchema::traverseRedefine(const DOM_Element& redefineElem) {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::GlobalContext;
- fAttributeCheck.checkAttributes(redefineElem, scope, this);
- // 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)) {
- return;
- }
- if (!fRedefineComponents) {
- fRedefineComponents = new RefHash2KeysTableOf<XMLCh>(13, false);
- }
- SchemaInfo* redefinedInfo = fSchemaInfo;
- renameRedefinedComponents(redefineElem, redefiningInfo, 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.
- restoreSchemaInfo(redefinedInfo);
- processChildren(fSchemaInfo->getRoot());
- // Now traverse our own <redefine>
- restoreSchemaInfo(redefiningInfo);
- 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 DOM_Element& elem,
- const int modelGroupType)
- {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // ------------------------------------------------------------------
- // Process contents
- // ------------------------------------------------------------------
- DOM_Element 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;
- DOMString childName = child.getLocalName();
- if (childName.equals(SchemaSymbols::fgELT_ELEMENT)) {
- bool toDelete = true;
- Janitor<QName> janQName(0);
- QName* eltQName = traverseElementDecl(child, toDelete);
- if (eltQName == 0) {
- continue;
- }
- if (toDelete) {
- janQName.reset(eltQName);
- }
- contentSpecNode = new ContentSpecNode(eltQName);
- seeParticle = true;
- }
- else if (childName.equals(SchemaSymbols::fgELT_GROUP)) {
- XercesGroupInfo* grpInfo = traverseGroupDecl(child);
- if (!grpInfo) {
- continue;
- }
- contentSpecNode = grpInfo->getContentSpec();
- if (!contentSpecNode) {
- continue;
- }
- if (hasAllContent(contentSpecNode)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AllContentLimited);
- continue;
- }
- contentSpecNode = new ContentSpecNode(*contentSpecNode);
- seeParticle = true;
- }
- else if (childName.equals(SchemaSymbols::fgELT_CHOICE)) {
- contentSpecNode = traverseChoiceSequence(child,ContentSpecNode::Choice);
- seeParticle = true;
- }
- else if (childName.equals(SchemaSymbols::fgELT_SEQUENCE)) {
- contentSpecNode = traverseChoiceSequence(child,ContentSpecNode::Sequence);
- seeParticle = true;
- }
- else if (childName.equals(SchemaSymbols::fgELT_ANY)) {
- contentSpecNode = traverseAny(child);
- seeParticle = true;
- }
- else {
- fBuffer.set(childName.rawBuffer(), childName.length());
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::GroupContentRestricted,
- fBuffer.getRawBuffer());
- }
- 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 ContentSpecNode((ContentSpecNode::NodeTypes) modelGroupType, left, right);
- right = contentSpecNode;
- }
- }
- if (hadContent) {
- left = new ContentSpecNode((ContentSpecNode::NodeTypes) modelGroupType, left, right);
- }
- return left;
- }
- /**
- * Traverse SimpleType declaration:
- * <simpleType
- * id = ID
- * name = NCName>
- * Content: (annotation? , ((list | restriction | union)))
- * </simpleType>
- *
- * traverse <list>|<restriction>|<union>
- */
- int TraverseSchema::traverseSimpleTypeDecl(const DOM_Element& childElem,
- int baseRefContext)
- {
- bool topLevel = isTopLevelComponent(childElem);
- // ------------------------------------------------------------------
- // Process contents
- // ------------------------------------------------------------------
- const XMLCh* name = getElementAttValue(childElem,SchemaSymbols::fgATT_NAME);
- if (topLevel && XMLString::stringLen(name) == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
- SchemaSymbols::fgELT_SIMPLETYPE);
- return -1;
- }
- if (XMLString::stringLen(name) == 0) { // anonymous simpleType
- name = genAnonTypeName(fgAnonSNamePrefix);
- }
- else if (!XMLString::isValidNCName(name)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
- SchemaSymbols::fgELT_SIMPLETYPE, name);
- return -1;
- }
- fBuffer.set(fTargetNSURIString);
- fBuffer.append(chComma);
- fBuffer.append(name);
- int fullTypeNameId = fStringPool->addOrFind(fBuffer.getRawBuffer());
- const XMLCh* fullName = fStringPool->getValueForId(fullTypeNameId);
- //check if we have already traversed the same simpleType decl
- if (fDatatypeRegistry->getDatatypeValidator(fullName)!= 0) {
- return fullTypeNameId;
- }
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = (topLevel) ? GeneralAttributeCheck::GlobalContext
- : GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(childElem, scope, this);
- // Circular constraint checking
- if (fCurrentTypeNameStack->containsElement(fullTypeNameId)){
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, name);
- return -1;
- }
- fCurrentTypeNameStack->addElement(fullTypeNameId);
- // Get 'final' values
- const XMLCh* finalVal = getElementAttValue(childElem, SchemaSymbols::fgATT_FINAL);
- int finalSet = parseFinalSet(finalVal, S_Final);
- // annotation?,(list|restriction|union)
- DOM_Element content= checkContent(childElem,
- XUtil::getFirstChildElement(childElem),
- false);
- if (content == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent);
- return resetCurrentTypeNameStack(-1);
- }
- DOMString varietyName = content.getLocalName();
- int newSimpleTypeName = fStringPool->addOrFind(name);
- // -----------------------------------------------------------------------
- // Check Attributes
- // -----------------------------------------------------------------------
- fAttributeCheck.checkAttributes(content, GeneralAttributeCheck::LocalContext, this);
- // Remark: some code will be repeated in list|restriction| union but it
- // is cleaner that way
- if (varietyName.equals(SchemaSymbols::fgELT_LIST)) { //traverse List
- if (baseRefContext & SchemaSymbols::LIST != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AtomicItemType);
- return resetCurrentTypeNameStack(-1);
- }
- return traverseByList(childElem, content, newSimpleTypeName, finalSet);
- }
- else if (varietyName.equals(SchemaSymbols::fgELT_RESTRICTION)) { //traverse Restriction
- return traverseByRestriction(childElem, content, newSimpleTypeName, finalSet);
- }
- else if (varietyName.equals(SchemaSymbols::fgELT_UNION)) { //traverse union
- return traverseByUnion(childElem, content, newSimpleTypeName, finalSet, baseRefContext);
- }
- else {
- fBuffer.set(varietyName.rawBuffer(), varietyName.length());
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::FeatureUnsupported,fBuffer.getRawBuffer());
- }
- return resetCurrentTypeNameStack(-1);
- }
- /**
- * 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 DOM_Element& elem) {
- // Get the attributes of the complexType
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- bool topLevel = isTopLevelComponent(elem);
- if (XMLString::stringLen(name) == 0) {
- if (topLevel) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameComplexType);
- return -1;
- }
- name = genAnonTypeName(fgAnonCNamePrefix);
- }
- if (!XMLString::isValidNCName(name)) {
- //REVISIT - Should we return or continue and save type with wrong name?
- reportSchemaError(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);
- if (topLevel) {
- ComplexTypeInfo* temp = fComplexTypeRegistry->get(fullName);
- if (temp != 0 ) {
- return typeNameIndex;
- }
- }
- // -----------------------------------------------------------------------
- // Check Attributes
- // -----------------------------------------------------------------------
- unsigned short scope = (topLevel) ? GeneralAttributeCheck::GlobalContext
- : GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // -----------------------------------------------------------------------
- // Create a new instance
- // -----------------------------------------------------------------------
- ComplexTypeInfo* typeInfo = new ComplexTypeInfo();
- int previousScope = fCurrentScope;
- fCurrentScope = fScopeCount++;
- // ------------------------------------------------------------------
- // First, handle any ANNOTATION declaration and get next child
- // ------------------------------------------------------------------
- DOM_Element child = checkContent(elem, XUtil::getFirstChildElement(elem),
- true);
- // ------------------------------------------------------------------
- // Register the type
- // ------------------------------------------------------------------
- // Register the type first, so that in case of a recursive element type
- // declaration, we can retrieve the complexType info (though the rest of
- fComplexTypeRegistry->put((void*) fullName, typeInfo);
- typeInfo->setTypeName(fullName);
- typeInfo->setScopeDefined(fCurrentScope);
- fCurrentTypeNameStack->addElement(typeNameIndex);
- ComplexTypeInfo* saveTypeInfo = fCurrentComplexType;
- fCurrentComplexType = typeInfo;
- // ------------------------------------------------------------------
- // Process the content of the complex type declaration
- // ------------------------------------------------------------------
- try {
- if (child == 0) {
- // EMPTY complexType with complexContent
- processComplexContent(name, child, typeInfo, 0,0,0, false);
- }
- else {
- DOMString childName = child.getLocalName();
- const XMLCh* mixedVal = getElementAttValue(elem,SchemaSymbols::fgATT_MIXED);
- bool isMixed = false;
- if (XMLString::stringLen(mixedVal)
- && (!XMLString::compareString(SchemaSymbols::fgATTVAL_TRUE, mixedVal)
- || !XMLString::compareString(fgValueOne, mixedVal))) {
- isMixed = true;
- }
- if (childName.equals(SchemaSymbols::fgELT_SIMPLECONTENT)) {
- // SIMPLE CONTENT element
- traverseSimpleContentDecl(name, child, typeInfo);
- if (XUtil::getNextSiblingElement(child) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingSimpleContent);
- }
- }
- else if (childName.equals(SchemaSymbols::fgELT_COMPLEXCONTENT)) {
- // COMPLEX CONTENT element
- traverseComplexContentDecl(name, child, typeInfo, isMixed);
- if (XUtil::getNextSiblingElement(child) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingConplexContent);
- }
- }
- else {
- // We must have ....
- // GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes
- // Note that it's possible that only attributes are specified.
- processComplexContent(name, child, typeInfo, 0, 0, 0, isMixed);
- }
- }
- }
- catch(TraverseSchema::ExceptionCodes) {
- defaultComplexTypeInfo(typeInfo);
- }
- // ------------------------------------------------------------------
- // Finish the setup of the typeInfo
- // ------------------------------------------------------------------
- const XMLCh* blockAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_BLOCK);
- const XMLCh* finalAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_FINAL);
- const XMLCh* abstractAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT);
- int blockSet = parseBlockSet(blockAttVal, C_Block);
- int finalSet = parseFinalSet(finalAttVal, EC_Final);
- typeInfo->setBlockSet(blockSet);
- typeInfo->setFinalSet(finalSet);
- if (XMLString::stringLen(abstractAttVal)
- && (!XMLString::compareString(abstractAttVal, SchemaSymbols::fgATTVAL_TRUE)
- || !XMLString::compareString(abstractAttVal, fgValueOne))) {
- typeInfo->setAbstract(true);
- }
- else {
- typeInfo->setAbstract(false);
- }
- // ------------------------------------------------------------------
- // Before exiting, restore the scope, mainly for nested anonymous types
- // ------------------------------------------------------------------
- fCurrentScope = previousScope;
- fCurrentComplexType = saveTypeInfo;
- resetCurrentTypeNameStack(0);
- 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 DOM_Element& elem) {
- bool topLevel = isTopLevelComponent(elem);
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
- bool nameEmpty = (XMLString::stringLen(name) == 0) ? true : false;
- bool refEmpty = (XMLString::stringLen(ref) == 0) ? true : false;
- if (nameEmpty && topLevel) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
- SchemaSymbols::fgELT_GROUP);
- return 0;
- }
- if (nameEmpty && refEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefGroup);
- return 0;
- }
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = (topLevel) ? GeneralAttributeCheck::GlobalContext
- : GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // ------------------------------------------------------------------
- // Check for annotations
- // ------------------------------------------------------------------
- DOM_Element 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(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 XercesGroupInfo();
- fCurrentGroupStack->addElement(nameIndex);
- fCurrentGroupInfo = groupInfo;
- if (!saveGroupInfo && !fCurrentComplexType) {
- fCurrentScope = fScopeCount++;
- }
- fCurrentGroupInfo->setScope(fCurrentScope);
- if (content == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::GroupContentError, name);
- }
- else {
- if (content.getAttributeNode(SchemaSymbols::fgATT_MINOCCURS) != 0
- || content.getAttributeNode(SchemaSymbols::fgATT_MAXOCCURS) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::MinMaxOnGroupChild);
- }
- bool illegalChild = false;
- DOMString childName = content.getLocalName();
- if (childName.equals(SchemaSymbols::fgELT_SEQUENCE)) {
- specNode = traverseChoiceSequence(content, ContentSpecNode::Sequence);
- }
- else if (childName.equals(SchemaSymbols::fgELT_CHOICE)) {
- specNode = traverseChoiceSequence(content, ContentSpecNode::Choice);
- }
- else if (childName.equals(SchemaSymbols::fgELT_ALL)) {
- specNode = traverseAll(content);
- }
- else {
- illegalChild = true;
- }
- if (illegalChild || XUtil::getNextSiblingElement(content) != 0) {
- reportSchemaError(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 (fRedefineComponents && fRedefineComponents->get(SchemaSymbols::fgELT_GROUP, nameIndex)) {
- fBuffer.set(fullName);
- fBuffer.append(SchemaSymbols::fgRedefIdentifier);
- XercesGroupInfo* baseGroupInfo = fGroupRegistry->get(fBuffer.getRawBuffer());
- try {
- checkParticleDerivationOk(groupInfo->getContentSpec(), groupInfo->getScope(),
- baseGroupInfo->getContentSpec(), baseGroupInfo->getScope());
- }
- catch (const XMLException& excep) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DisplayErrorMessage, excep.getMessage());
- }
- }
- return groupInfo;
- }
- /**
- * Traverse attributeGroup Declaration.
- *
- * <attributeGroup
- * id = ID
- * name = NCName
- * ref = QName>
- * Content: (annotation? , (attribute|attributeGroup)*, anyAttribute?)
- * <attributeGroup/>
- *
- */
- XercesAttGroupInfo*
- TraverseSchema::traverseAttributeGroupDecl(const DOM_Element& elem,
- ComplexTypeInfo* const typeInfo) {
- bool topLevel = isTopLevelComponent(elem);
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
- bool nameEmpty = (XMLString::stringLen(name) == 0) ? true : false;
- bool refEmpty = (XMLString::stringLen(ref) == 0) ? true : false;
- if (nameEmpty && topLevel) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
- SchemaSymbols::fgELT_ATTRIBUTEGROUP);
- return 0;
- }
- if (nameEmpty && refEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttGroup);
- return 0;
- }
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = (topLevel) ? GeneralAttributeCheck::GlobalContext
- : GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // ------------------------------------------------------------------
- // 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(XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
- SchemaSymbols::fgELT_ATTRIBUTEGROUP, name);
- return 0;
- }
- // ------------------------------------------------------------------
- // Check for annotations
- // ------------------------------------------------------------------
- DOM_Element content = checkContent(elem, XUtil::getFirstChildElement(elem),
- true);
- // ------------------------------------------------------------------
- // Process contents of global attributeGroups
- // ------------------------------------------------------------------
- XercesAttGroupInfo* saveAttGroupInfo = fCurrentAttGroupInfo;
- XercesAttGroupInfo* attGroupInfo = new XercesAttGroupInfo();
- fAttGroupRegistry->put((void*) name, attGroupInfo);
- fCurrentAttGroupInfo = attGroupInfo;
- for (; content !=0; content = XUtil::getNextSiblingElement(content)) {
- if (content.getLocalName().equals(SchemaSymbols::fgELT_ATTRIBUTE)) {
- traverseAttributeDecl(content, typeInfo);
- }
- else if (content.getLocalName().equals(SchemaSymbols::fgELT_ATTRIBUTEGROUP)) {
- traverseAttributeGroupDecl(content, typeInfo);
- }
- else {
- break;
- }
- }
- if (content != 0) {
- if (content.getLocalName().equals(SchemaSymbols::fgELT_ANYATTRIBUTE)) {
- SchemaAttDef* anyAtt = traverseAnyAttribute(content);
- if (anyAtt) {
- fCurrentAttGroupInfo->addAnyAttDef(anyAtt);
- }
- if (XUtil::getNextSiblingElement(content) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttGroupContentError, name);
- }
- }
- else {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttGroupContentError, name);
- }
- }
- // ------------------------------------------------------------------
- // Restore old 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(baseAttGroupInfo, attGroupInfo);
- }
- }
- return attGroupInfo;
- }
- inline XercesAttGroupInfo*
- TraverseSchema::traverseAttributeGroupDeclNS(const XMLCh* const uriStr,
- const XMLCh* const name) {
- // ------------------------------------------------------------------
- // Get grammar information
- // ------------------------------------------------------------------
- Grammar* aGrammar = fGrammarResolver->getGrammar(uriStr);
- if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) {
- reportSchemaError(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 DOM_Element& elem) {
- // -----------------------------------------------------------------------
- // Check Attributes
- // -----------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // ------------------------------------------------------------------
- // First, handle any ANNOTATION declaration
- // ------------------------------------------------------------------
- if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0) {
- reportSchemaError(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 (XMLString::stringLen(processContents) > 0
- && XMLString::compareString(processContents, fgStrict)) {
- if (!XMLString::compareString(processContents, fgLax)) {
- anyType = ContentSpecNode::Any_Lax;
- anyOtherType = ContentSpecNode::Any_Other_Lax;
- anyLocalType = ContentSpecNode::Any_NS_Lax;
- }
- else if (!XMLString::compareString(processContents, fgSkip)) {
- anyType = ContentSpecNode::Any_Skip;
- anyOtherType = ContentSpecNode::Any_Other_Skip;
- anyLocalType = ContentSpecNode::Any_NS_Skip;
- }
- }
- // ------------------------------------------------------------------
- // Process 'namespace' attribute
- // ------------------------------------------------------------------
- ContentSpecNode* retSpecNode = 0;
- if (XMLString::stringLen(nameSpace) == 0
- || !XMLString::compareString(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDANY)) {
- retSpecNode = new ContentSpecNode(new QName(XMLUni::fgZeroLenString,
- XMLUni::fgZeroLenString,
- fEmptyNamespaceURI),
- false);
- retSpecNode->setType(anyType);
- }
- else if (!XMLString::compareString(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER)) {
- retSpecNode = new ContentSpecNode(new QName(XMLUni::fgZeroLenString,
- XMLUni::fgZeroLenString,
- fTargetNSURI),
- false);
- retSpecNode->setType(anyOtherType);
- }
- else {
- RefVectorOf<XMLCh>* nameSpaceTokens = XMLString::tokenizeString(nameSpace);
- ValueVectorOf<unsigned int> uriList(8);
- ContentSpecNode* firstNode = 0;
- ContentSpecNode* secondNode = 0;
- unsigned int tokensSize = nameSpaceTokens->size();
- for (unsigned int i=0; i < tokensSize; i++) {
- const XMLCh* tokenElem = nameSpaceTokens->elementAt(i);
- int uriIndex = fEmptyNamespaceURI;
- if (XMLString::compareString(tokenElem,SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL)) { // not ##local
- if (!XMLString::compareString(tokenElem,SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE)) {
- uriIndex = fTargetNSURI;
- }
- else {
- uriIndex = fURIStringPool->addOrFind(tokenElem);
- }
- }
- if (uriList.containsElement(uriIndex)) {
- continue;
- }
- uriList.addElement(uriIndex);
- firstNode = new ContentSpecNode(new QName(XMLUni::fgZeroLenString,
- XMLUni::fgZeroLenString,
- uriIndex),
- false);
- firstNode->setType(anyLocalType);
- if (secondNode == 0) {
- secondNode = firstNode;
- }
- else {
- secondNode = new ContentSpecNode(ContentSpecNode::Choice, secondNode, firstNode);
- }
- }
- 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 DOM_Element& elem) {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // ------------------------------------------------------------------
- // Process contents
- // ------------------------------------------------------------------
- DOM_Element 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;
- DOMString childName = child.getLocalName();
- if (childName.equals(SchemaSymbols::fgELT_ELEMENT)) {
- bool toDelete = true;
- Janitor<QName> janQName(0);
- QName* eltQName = traverseElementDecl(child, toDelete);
- if (eltQName == 0) {
- continue;
- }
- if (toDelete) {
- janQName.reset(eltQName);
- }
- contentSpecNode = new ContentSpecNode(eltQName);
- checkMinMax(contentSpecNode, child, All_Element);
- }
- else {
- fBuffer.set(childName.rawBuffer(), childName.length());
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AllContentError, fBuffer.getRawBuffer());
- continue;
- }
- hadContent = true;
- if (!left) {
- left = contentSpecNode;
- }
- else if (!right) {
- right = contentSpecNode;
- }
- else {
- left = new ContentSpecNode(ContentSpecNode::All, left, right);
- right = contentSpecNode;
- }
- }
- if (hadContent) {
- left = new ContentSpecNode(ContentSpecNode::All, left, right);
- }
- 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 DOM_Element& elem,
- ComplexTypeInfo* const typeInfo) {
- bool topLevel = isTopLevelComponent(elem);
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
- bool nameEmpty = (XMLString::stringLen(name) == 0) ? true : false;
- bool refEmpty = (XMLString::stringLen(ref) == 0) ? true : false;
- if (nameEmpty && refEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttribute);
- return;
- }
- if (topLevel) {
- if (nameEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameAttribute);
- return;
- }
- else {
- if (!refEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::GlobalAttributeWithNameRef, name);
- }
- }
- }
- else {
- if (!typeInfo && !fCurrentAttGroupInfo) {
- // Nothing to do - where to save that attribute info?
- return;
- }
- }
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = (topLevel) ? GeneralAttributeCheck::GlobalContext
- : GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- 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);
- DOM_Element simpleType = checkContent(elem, XUtil::getFirstChildElement(elem), true);
- bool badContent = false;
- while (simpleType != 0) {
- DOMString contentName = simpleType.getLocalName();
- fBuffer.set(contentName.rawBuffer(), contentName.length());
- if (XMLString::compareString(SchemaSymbols::fgELT_SIMPLETYPE,
- fBuffer.getRawBuffer()) == 0) {
- if (XUtil::getNextSiblingElement(simpleType) != 0) {
- badContent = true;
- }
- break;
- }
- badContent = true;
- simpleType = XUtil::getNextSiblingElement(simpleType);
- }
- if (badContent) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttributeContent,
- (name) ? SchemaSymbols::fgATT_NAME : SchemaSymbols::fgATT_REF,
- (name) ? name : ref);
- }
- if (defaultVal) {
- if (fixedVal) {
- fixedVal = 0;
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeDefaultFixedValue);
- }
- if (XMLString::stringLen(useVal) != 0
- && XMLString::compareString(useVal, SchemaSymbols::fgATTVAL_OPTIONAL) != 0) {
- useVal = 0;
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NotOptionalDefaultAttValue);
- }
- }
- // processing ref
- if (nameEmpty || (!refEmpty && !topLevel)) {
- if (!nameEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::LocalAttributeWithNameRef, name);
- }
- // Check ref representation OK - 3.2.3::3.2
- if (attForm || dvType || (simpleType != 0)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeRefContentError);
- }
- processAttributeDeclRef(elem, typeInfo, ref, useVal, defaultVal, fixedVal);
- return;
- }
- // processing 'name'
- if (!XMLString::isValidNCName(name)
- || XMLString::compareString(name, XMLUni::fgXMLNSString) == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ATTRIBUTE, name);
- return;
- }
- // Check for duplicate declaration
- const XMLCh* qualified = SchemaSymbols::fgATTVAL_QUALIFIED;
- int uriIndex = fEmptyNamespaceURI;
- if (XMLString::stringLen(fTargetNSURIString) != 0
- && (topLevel || XMLString::compareString(attForm, qualified) == 0
- || ((fSchemaInfo->getElemAttrDefaultQualified() & Attr_Def_Qualified)
- && XMLString::stringLen(attForm) == 0))) {
- uriIndex = fTargetNSURI;
- }
- if (typeInfo && typeInfo->getAttDef(name, uriIndex) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name);
- return;
- }
- else if (fCurrentAttGroupInfo && fCurrentAttGroupInfo->containsAttribute(name, uriIndex)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name);
- return;
- }
- DatatypeValidator* dv = 0;
- XMLAttDef::AttTypes attType;
- SchemaInfo* saveInfo = fSchemaInfo;
- if (simpleType != 0) {
- if (XMLString::stringLen(dvType) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeWithTypeAndSimpleType);
- }
- int datatypeSymbol = traverseSimpleTypeDecl(simpleType);
- attType = XMLAttDef::Simple;
- if (datatypeSymbol != -1) {
- dv = fDatatypeRegistry->getDatatypeValidator(fStringPool->getValueForId(datatypeSymbol));
- }
- }
- else if (XMLString::stringLen(dvType) == 0) {
- attType = XMLAttDef::Simple;
- dv = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_STRING);
- }
- else {
- checkEnumerationRequiredNotation(name, dvType);
- const XMLCh* localPart = getLocalPart(dvType);
- const XMLCh* prefix = getPrefix(dvType);
- const XMLCh* typeURI = resolvePrefixToURI(prefix);
- if (XMLString::compareString(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) == 0) {
- dv = getDatatypeValidator(SchemaSymbols::fgURI_SCHEMAFORSCHEMA, localPart);
- if (XMLString::compareString(localPart,XMLUni::fgIDString) == 0) {
- attType = XMLAttDef::ID;
- }
- else if (XMLString::compareString(localPart,XMLUni::fgIDRefString) == 0) {
- attType = XMLAttDef::IDRef;
- }
- else if (XMLString::compareString(localPart,XMLUni::fgIDRefsString) == 0) {
- attType = XMLAttDef::IDRefs;
- }
- else if (XMLString::compareString(localPart,XMLUni::fgEntityString) == 0) {
- attType = XMLAttDef::Entity;
- }
- else if (XMLString::compareString(localPart,XMLUni::fgEntitiesString) == 0) {
- attType = XMLAttDef::Entities;
- }
- else if (XMLString::compareString(localPart,XMLUni::fgNmTokenString) == 0) {
- attType = XMLAttDef::NmToken;
- }
- else if (XMLString::compareString(localPart,XMLUni::fgNmTokensString) == 0) {
- attType = XMLAttDef::NmTokens;
- }
- else if (XMLString::compareString(localPart,XMLUni::fgNotationString) == 0) {
- attType = XMLAttDef::Notation;
- }
- else {
- attType = XMLAttDef::Simple;
- if (dv == 0 && XMLString::stringLen(typeURI) == 0) {
- DOM_Element topLevelType =
- fSchemaInfo->getTopLevelComponent(SchemaSymbols::fgELT_SIMPLETYPE, localPart, &fSchemaInfo);
- if (topLevelType != 0) {
- traverseSimpleTypeDecl(topLevelType);
- dv = getDatatypeValidator(typeURI, localPart);
- }
- else {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeSimpleTypeNotFound,
- typeURI, localPart, name);
- }
- }
- }
- }
- else { //isn't of the schema for schemas namespace...
- // check if the type is from the same Schema
- dv = getDatatypeValidator(typeURI, localPart);
- if (dv == 0 && !XMLString::compareString(typeURI, fTargetNSURIString)) {
- DOM_Element topLevelType =
- fSchemaInfo->getTopLevelComponent(SchemaSymbols::fgELT_SIMPLETYPE, localPart, &fSchemaInfo);
- if (topLevelType != 0) {
- traverseSimpleTypeDecl(topLevelType);
- dv = getDatatypeValidator(typeURI, localPart);
- }
- else {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttributeSimpleTypeNotFound,
- typeURI, localPart, name);
- }
- }
- attType = XMLAttDef::Simple;
- }
- if (!dv) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, typeURI, localPart);
- }
- }
- // restore schema information, if necessary
- fSchemaInfo = saveInfo;
- bool required = false;
- bool prohibited = false;
- if (XMLString::stringLen(useVal) != 0) {
- if (!XMLString::compareString(useVal, SchemaSymbols::fgATTVAL_REQUIRED)) {
- required = true;
- }
- else if (!XMLString::compareString(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) {
- if (ofTypeID) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3,
- SchemaSymbols::fgATT_NAME, name);
- }
- else {
- try {
- dv->validate(valueToCheck);
- }
- catch (const XMLException& excep) {
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::DisplayErrorMessage, excep.getMessage());
- }
- catch(...) {
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueToCheck);
- }
- }
- }
- // check for multiple attributes with type derived from ID
- if (!topLevel && ofTypeID) {
- if (fCurrentAttGroupInfo) {
- if (fCurrentAttGroupInfo->containsTypeWithId()) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, name);
- return;
- }
- fCurrentAttGroupInfo->setTypeWithId(true);
- }
- else {
- if (typeInfo->containsAttWithTypeId()) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, name);
- return;
- }
- typeInfo->setAttWithTypeId(true);
- }
- }
- // create SchemaAttDef
- SchemaAttDef* attDef = new SchemaAttDef(XMLUni::fgZeroLenString, name, uriIndex, attType);
- 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*) 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 DOM_Element& elem, bool& toDelete) {
- bool topLevel = isTopLevelComponent(elem);
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF);
- const XMLCh* fixed = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED);
- const XMLCh* deflt = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT);
- bool nameEmpty = (XMLString::stringLen(name) == 0) ? true : false;
- bool refEmpty = (XMLString::stringLen(ref) == 0) ? true : false;
- if (nameEmpty && topLevel) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::GlobalNoNameElement);
- return 0;
- }
- if (nameEmpty && refEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefElement);
- return 0;
- }
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = (topLevel) ? GeneralAttributeCheck::GlobalContext
- : GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(elem, scope, this);
- // ------------------------------------------------------------------
- // Process contents
- // ------------------------------------------------------------------
- if(XMLString::stringLen(fixed) != 0 && XMLString::stringLen(deflt) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ElementWithFixedAndDefault);
- }
- if (nameEmpty || (!refEmpty && !topLevel)) {
- if (!nameEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DeclarationWithNameRef,
- SchemaSymbols::fgELT_ELEMENT, name);
- }
- if (!isValidRefDeclaration(elem)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::BadAttWithRef);
- }
- return processElementDeclRef(elem, ref, toDelete);
- }
- // Name is notEmpty
- if (!XMLString::isValidNCName(name)) {
- reportSchemaError(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;
- if (topLevel) {
- if (!refEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::GlobalElementWithRef, name);
- }
- if (fSchemaGrammar->getElemDecl(fTargetNSURI, name, 0, Grammar::TOP_LEVEL_SCOPE) != 0) {
- return new QName(name, fTargetNSURI);
- }
- }
- // 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
- DOM_Element content = checkContent(elem, XUtil::getFirstChildElement(elem), true);
- if (content != 0) {
- DOMString contentName = content.getLocalName();
- if (contentName.equals(SchemaSymbols::fgELT_COMPLEXTYPE)) {
- if (content.getAttribute(SchemaSymbols::fgATT_NAME).length() > 0) {
- // REVISIT - we are bypassing the complex type declaration.
- // Is this the right way to go?
- noErrorFound = false;
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AnonComplexTypeWithName, name);
- }
- else {
- typeInfo = checkForComplexTypeInfo(content);
- }
- if (typeInfo == 0) {
- noErrorFound = false;
- }
- else if (!isDuplicate) {
- typeInfo->setElementId(elemDecl->getId());
- }
- anonymousType = true;
- content = XUtil::getNextSiblingElement(content);
- }
- else if (contentName.equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
- if (content.getAttribute(SchemaSymbols::fgATT_NAME).length() > 0) {
- // REVISIT - we are bypassing the simple type declaration.
- // Is this the right way to go?
- noErrorFound = false;
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AnonSimpleTypeWithName, name);
- }
- else {
- validator = checkForSimpleTypeValidator(content);
- }
- if (validator == 0) {
- 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(XMLUni::fgXMLErrDomain, XMLErrs::InvalidElementContent);
- }
- }
- }
- // Handle 'type' attribute
- const XMLCh* typeStr = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE);
- if (XMLString::stringLen(typeStr) > 0) {
- if (anonymousType) {
- noErrorFound = false;
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ElementWithTypeAndAnonType, name);
- }
- else {
- if (!isAnyType(typeStr)) {
- checkEnumerationRequiredNotation(name, typeStr);
- anotherSchemaURI = checkTypeFromAnotherSchema(typeStr);
- // get complex type info
- typeInfo = getElementComplexTypeInfo(typeStr, noErrorFound, anotherSchemaURI);
- // get simple type validtor - if not a complex type
- if (typeInfo == 0) {
- validator = getElementTypeValidator(typeStr, noErrorFound,
- anotherSchemaURI,true);
- }
- }
- }
- }
- // Set element declararion type information - handle case when we have
- // circular substitution group (a subs b and b subs a)
- if (!isDuplicate) {
- elemDecl->setDatatypeValidator(validator);
- elemDecl->setComplexTypeInfo(typeInfo);
- }
- // Handle the substitutionGroup
- const XMLCh* subsGroupName =
- getElementAttValue(elem, SchemaSymbols::fgATT_SUBSTITUTIONGROUP);
- if (XMLString::stringLen(subsGroupName) != 0) {
- SchemaElementDecl* subsElemDecl = getSubstituteGroupElemDecl(subsGroupName, noErrorFound);
- if (subsElemDecl != 0) {
- // An element cannot substitute itself
- if (subsElemDecl == elemDecl) {
- // REVISIT - add proper error message
- }
- else {
- // Check for substitution validity constraint
- // Substitution allowed (block and blockDefault) && same type
- if (isSubstitutionGroupValid(subsElemDecl,typeInfo,validator,name)) {
- if (typeInfo == 0 && validator == 0 && noErrorFound) {
- typeInfo = subsElemDecl->getComplexTypeInfo();
- validator = subsElemDecl->getDatatypeValidator();
- }
- // set element substitutionGroup full name
- const XMLCh* uri = resolvePrefixToURI(getPrefix(subsGroupName));
- const XMLCh* localPart = getLocalPart(subsGroupName);
- fBuffer.set(uri);
- fBuffer.append(chComma);
- fBuffer.append(localPart);
- if (!isDuplicate) {
- XMLCh* elemBaseName = elemDecl->getBaseName();
- XMLCh* subsElemBaseName = subsElemDecl->getBaseName();
- int elemURI = elemDecl->getURI();
- int subsElemURI = subsElemDecl->getURI();
- elemDecl->setSubstitutionGroupName(fBuffer.getRawBuffer());
- fSubstitutionGroups->put((void*) elemBaseName, elemURI, subsElemDecl);
- ValueVectorOf<SchemaElementDecl*>* 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 ValueVectorOf<SchemaElementDecl*>(*subsElements);
- fValidSubstitutionGroups->put(subsElemBaseName, subsElemURI, subsElements);
- }
- else if (fSchemaInfo->circularImportExist(subsElemURI)) {
- aGrammar->getValidSubstitutionGroups()->put(
- subsElemBaseName, subsElemURI, new ValueVectorOf<SchemaElementDecl*>(8));
- }
- }
- }
- if (!subsElements) {
- subsElements = new ValueVectorOf<SchemaElementDecl*>(8);
- fValidSubstitutionGroups->put(subsElemBaseName, subsElemURI, subsElements);
- }
- subsElements->addElement(elemDecl);
- // update related subs. info in case of circular import
- RefVectorEnumerator<SchemaInfo> importingEnum = fSchemaInfo->getImportingListEnumerator();
- while (importingEnum.hasMoreElements()) {
- const SchemaInfo& curRef = importingEnum.nextElement();
- SchemaGrammar* aGrammar = (SchemaGrammar*)
- fGrammarResolver->getGrammar(curRef.getTargetNSURIString());
- ValueVectorOf<SchemaElementDecl*>* subsElemList =
- aGrammar->getValidSubstitutionGroups()->get(subsElemBaseName, subsElemURI);
- if (subsElemList && !subsElemList->containsElement(elemDecl)) {
- subsElemList->addElement(elemDecl);
- }
- }
- buildValidSubstitutionListB(elemDecl, subsElemDecl);
- buildValidSubstitutionListF(elemDecl, subsElemDecl);
- }
- }
- else {
- noErrorFound = false;
- }
- }
- }
- }
- if (typeInfo == 0 && validator == 0) {
- if (noErrorFound) { // ur type
- contentSpecType = SchemaElementDecl::Any;
- }
- else {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UntypedElement, name);
- }
- }
- // if element belongs to a compelx type
- if (typeInfo != 0) {
- contentSpecNode = typeInfo->getContentSpec();
- contentSpecType = (SchemaElementDecl::ModelTypes) typeInfo->getContentType();
- scopeDefined = typeInfo->getScopeDefined();
- validator = typeInfo->getDatatypeValidator();
- }
- // if element belongs to a simple type
- if (validator != 0) {
- contentSpecType = SchemaElementDecl::Simple;
- if (typeInfo == 0) {
- anotherSchemaURI = 0; // not to switch schema in this case
- }
- }
- // Now we can handle validation etc. of default and fixed attributes,
- // since we finally have all the type information.
- if(XMLString::stringLen(fixed) != 0) {
- deflt = fixed;
- }
- if(XMLString::stringLen(deflt) != 0) {
- try {
- if(validator == 0) { // in this case validate according to xs:string
- fDatatypeRegistry->getDatatypeValidator(
- SchemaSymbols::fgDT_STRING)->validate(deflt);
- } else {
- validator->validate(deflt);
- }
- }
- catch (const XMLException& excep) {
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::DisplayErrorMessage, excep.getMessage());
- }
- catch(...) {
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, deflt);
- }
- if(typeInfo != 0 &&
- contentSpecType != SchemaElementDecl::Simple &&
- contentSpecType != SchemaElementDecl::Mixed_Simple &&
- contentSpecType != SchemaElementDecl::Mixed_Complex) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NotSimpleOrMixedElement, name);
- }
- if(typeInfo != 0 &&
- ((contentSpecType == SchemaElementDecl::Mixed_Complex
- || contentSpecType == SchemaElementDecl::Mixed_Simple)
- && !emptiableParticle(contentSpecNode))) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::EmptiableMixedContent, name);
- }
- if (validator && (validator->getType() == DatatypeValidator::ID)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ElemIDValueConstraint, name, deflt);
- }
- }
- // set element information, but first check for duplicate elements with
- // different types.
- if (isDuplicate) {
- DatatypeValidator* eltDV = elemDecl->getDatatypeValidator();
- ComplexTypeInfo* eltTypeInfo = elemDecl->getComplexTypeInfo();
- if ( (eltTypeInfo != typeInfo) || (eltDV != validator)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, name);
- }
- }
- else {
- elemDecl->setDatatypeValidator(validator);
- elemDecl->setComplexTypeInfo(typeInfo);
- elemDecl->setDefaultValue(deflt);
- elemDecl->setDefinedScope(scopeDefined);
- elemDecl->setModelType(contentSpecType);
- elemDecl->setContentSpec(contentSpecNode);
- elemDecl->setTypeFromAnotherSchemaURI(anotherSchemaURI);
- // key/keyref/unique processing
- DOM_Element ic = XUtil::getFirstChildElementNS(elem, fgIdentityConstraints,
- SchemaSymbols::fgURI_SCHEMAFORSCHEMA, 3);
- ValueVectorOf<DOM_Element>* icNodes = 0;
- while (ic != 0) {
- if ( ic.getLocalName().equals(SchemaSymbols::fgELT_KEY) ) {
- traverseKey(ic, elemDecl);
- }
- else if ( ic.getLocalName().equals(SchemaSymbols::fgELT_UNIQUE) ) {
- traverseUnique(ic, elemDecl);
- }
- else {
- if (!icNodes) {
- icNodes = new ValueVectorOf<DOM_Element>(8);
- }
- icNodes->addElement(ic);
- }
- ic = XUtil::getNextSiblingElementNS(ic, fgIdentityConstraints,
- SchemaSymbols::fgURI_SCHEMAFORSCHEMA, 3);
- }
- if (icNodes) {
- if (!fIC_ElementsNS) {
- fIC_ElementsNS = new RefHashTableOf<ElemVector>(13);
- fIC_NamespaceDepthNS = new RefHashTableOf<ValueVectorOf<unsigned int> >(13);
- fIC_NodeListNS = new RefHashTableOf<ValueVectorOf<DOM_Element> >(29, true, new HashPtr());
- }
- if (fIC_ElementsNS->containsKey(fTargetNSURIString)) {
- fIC_Elements = fIC_ElementsNS->get(fTargetNSURIString);
- fIC_NamespaceDepth = fIC_NamespaceDepthNS->get(fTargetNSURIString);
- }
- if (!fIC_Elements) {
- fIC_Elements = new ValueVectorOf<SchemaElementDecl*>(8);
- fIC_NamespaceDepth = new ValueVectorOf<unsigned int>(8);
- fIC_ElementsNS->put((void*) fTargetNSURIString, fIC_Elements);
- fIC_NamespaceDepthNS->put((void*) fTargetNSURIString, fIC_NamespaceDepth);
- }
- fIC_NodeListNS->put(elemDecl, icNodes);
- fIC_Elements->addElement(elemDecl);
- fIC_NamespaceDepth->addElement(fSchemaInfo->getNamespaceScopeLevel());
- }
- }
- return new QName(elemDecl->getElementName());
- }
- const XMLCh* TraverseSchema::traverseNotationDecl(const DOM_Element& elem) {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- fAttributeCheck.checkAttributes(elem, GeneralAttributeCheck::GlobalContext, this);
- // ------------------------------------------------------------------
- // Process notation attributes/elements
- // ------------------------------------------------------------------
- const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME);
- bool nameEmpty = (XMLString::stringLen(name) == 0) ? true : false;
- if (nameEmpty) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
- SchemaSymbols::fgELT_NOTATION);
- return 0;
- }
- if (fNotationRegistry->containsKey(name, fTargetNSURI)) {
- return name;
- }
- const XMLCh* publicId = getElementAttValue(elem, SchemaSymbols::fgATT_PUBLIC);
- const XMLCh* systemId = getElementAttValue(elem, SchemaSymbols::fgATT_SYSTEM);
- if (XMLString::stringLen(publicId) == 0 && XMLString::stringLen(systemId) == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::Notation_InvalidDecl, name);
- }
- fNotationRegistry->put((void*) name, fTargetNSURI, 0);
- //we don't really care if something inside <notation> is wrong..
- checkContent(elem, XUtil::getFirstChildElement(elem), true);
- return name;
- }
- const XMLCh* TraverseSchema::traverseNotationDecl(const XMLCh* const name,
- const XMLCh* const uriStr) {
- unsigned int uriId = fURIStringPool->addOrFind(uriStr);
- SchemaInfo* saveInfo = fSchemaInfo;
- if (fTargetNSURI != (int) uriId) {
- Grammar* grammar = fGrammarResolver->getGrammar(uriStr);
- if (grammar == 0 || grammar->getGrammarType() != Grammar::SchemaGrammarType) {
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr);
- return 0;
- }
- SchemaInfo* impInfo = fSchemaInfo->getImportInfo(uriId);
- if (!impInfo) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::TypeNotFound, uriStr, name);
- return 0;
- }
- fSchemaInfo = impInfo;
- fTargetNSURI = fSchemaInfo->getTargetNSURI();
- }
- DOM_Element notationElem = fSchemaInfo->getTopLevelComponent(SchemaSymbols::fgELT_NOTATION, name, &fSchemaInfo);
- if (notationElem == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::Notation_DeclNotFound, uriStr, name);
- return 0;
- }
- const XMLCh* notationName = traverseNotationDecl(notationElem);
- fSchemaInfo = saveInfo;
- fTargetNSURI = fSchemaInfo->getTargetNSURI();
- return notationName;
- }
- int TraverseSchema::traverseByList(const DOM_Element& rootElem,
- const DOM_Element& contentElem,
- const int typeNameIndex,
- const int finalSet) {
- DatatypeValidator* baseValidator = 0;
- DOM_Element content = contentElem;
- const XMLCh* typeName = fStringPool->getValueForId(typeNameIndex);
- const XMLCh* baseTypeName = getElementAttValue(content,
- SchemaSymbols::fgATT_ITEMTYPE);
- if (XUtil::getNextSiblingElement(content) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError);
- }
- if (XMLString::stringLen(baseTypeName) == 0) { // must 'see' <simpleType>
- content = checkContent(rootElem, XUtil::getFirstChildElement(content), false);
- if (content == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInList, typeName);
- return resetCurrentTypeNameStack(-1);
- }
- if (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
- baseValidator = checkForSimpleTypeValidator(content, SchemaSymbols::LIST);
- }
- else {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
- return resetCurrentTypeNameStack(-1);
- }
- content = XUtil::getNextSiblingElement(content);
- }
- else { // base was provided - get proper validator
- baseValidator = findDTValidator(rootElem, baseTypeName,
- SchemaSymbols::LIST);
- content = checkContent(rootElem, XUtil::getFirstChildElement(content), true);
- }
- if (baseValidator == 0) {
- return resetCurrentTypeNameStack(-1);
- }
- if (!baseValidator->isAtomic()) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::AtomicItemType, baseTypeName);
- return resetCurrentTypeNameStack(-1);
- }
- // '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(XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeDerivationByListError, typeName);
- }
- // create & register validator for "generated" type if it doesn't exist
- int strId = fStringPool->addOrFind(getQualifiedName(typeNameIndex));
- const XMLCh* qualifiedName = fStringPool->getValueForId(strId);
- try {
- DatatypeValidator* newValidator =
- fDatatypeRegistry->getDatatypeValidator(qualifiedName);
- if (newValidator == 0) {
- fDatatypeRegistry->createDatatypeValidator(
- qualifiedName, baseValidator, 0, 0, true, finalSet);
- }
- }
- catch (const XMLException& excep) {
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::DisplayErrorMessage, excep.getMessage());
- }
- catch(...) {
- reportSchemaError(XMLUni::fgXMLErrDomain,
- XMLErrs::DatatypeValidatorCreationError, typeName);
- }
- return resetCurrentTypeNameStack(strId);
- }
- int TraverseSchema::traverseByRestriction(const DOM_Element& rootElem,
- const DOM_Element& contentElem,
- const int typeNameIndex,
- const int finalSet) {
- DatatypeValidator* baseValidator = 0;
- DOM_Element content = contentElem;
- const XMLCh* typeName = fStringPool->getValueForId(typeNameIndex);
- const XMLCh* baseTypeName = getElementAttValue(content,
- SchemaSymbols::fgATT_BASE);
- if (XUtil::getNextSiblingElement(content) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError);
- }
- if (XMLString::stringLen(baseTypeName) == 0) { // must 'see' <simpleType>
- content = checkContent(rootElem, XUtil::getFirstChildElement(content), false);
- if (content == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInRestriction);
- return resetCurrentTypeNameStack(-1);
- }
- if (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
- baseValidator = checkForSimpleTypeValidator(content);
- }
- else {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
- return resetCurrentTypeNameStack(-1);
- }
- // Check for facets
- content = XUtil::getNextSiblingElement(content);
- }
- else { // base was provided - get proper validator
- baseValidator = findDTValidator(rootElem, baseTypeName,
- SchemaSymbols::RESTRICTION);
- content = checkContent(rootElem, XUtil::getFirstChildElement(content), true);
- }
- if (baseValidator == 0) {
- return resetCurrentTypeNameStack(-1);
- }
- // Get facets if any existing
- RefHashTableOf<KVStringPair>* facets = 0;
- RefVectorOf<XMLCh>* enums = 0;
- XMLBuffer pattern;
- DOMString facetName;
- XMLCh fixedFlagStr[16];
- unsigned int fixedFlag = 0;
- unsigned int scope = GeneralAttributeCheck::LocalContext;
- bool isFirstPattern = true;
- while (content != 0) {
- if (content.getNodeType() == DOM_Node::ELEMENT_NODE) {
- fAttributeCheck.checkAttributes(content, scope, this);
- facetName = content.getLocalName();
- fBuffer.set(facetName.rawBuffer(), facetName.length());
- int facetId = fStringPool->addOrFind(fBuffer.getRawBuffer());
- const XMLCh* facetStr = fStringPool->getValueForId(facetId);
- DOMString attValue = content.getAttribute(SchemaSymbols::fgATT_VALUE);
- int attValueLen = attValue.length();
- if (facets == 0) {
- facets = new RefHashTableOf<KVStringPair>(29, true);
- }
- if (XMLString::compareString(facetStr,
- SchemaSymbols::fgELT_ENUMERATION) == 0) {
- // 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) {
- enums = new RefVectorOf<XMLCh>(8, true);
- }
- fBuffer.set(attValue.rawBuffer(), attValueLen);
- if (baseValidator->getType() == DatatypeValidator::NOTATION) {
- unsigned int enumValId = fStringPool->addOrFind(fBuffer.getRawBuffer());
- const XMLCh* const enumVal = fStringPool->getValueForId(enumValId);
- const XMLCh* localPart = getLocalPart(enumVal);
- const XMLCh* prefix = getPrefix(enumVal);
- const XMLCh* uriStr = (XMLString::stringLen(prefix)) ? resolvePrefixToURI(prefix) : fTargetNSURIString;
- unsigned int uriId = fURIStringPool->addOrFind(uriStr);
- if (!fNotationRegistry->containsKey(localPart, uriId)) {
- traverseNotationDecl(localPart, uriStr);
- }
- fBuffer.set(uriStr);
- fBuffer.append(chColon);
- fBuffer.append(localPart);
- }
- enums->addElement(XMLString::replicate(fBuffer.getRawBuffer()));
- }
- else if (XMLString::compareString(facetStr,
- SchemaSymbols::fgELT_PATTERN) == 0) {
- if (isFirstPattern) { // fBuffer.isEmpty() - overhead call
- isFirstPattern = false;
- pattern.set(attValue.rawBuffer(), attValueLen);
- }
- else { //datatypes: 5.2.4 pattern
- pattern.append(chPipe);
- pattern.append(attValue.rawBuffer(), attValueLen);
- }
- }
- else if (XMLString::compareString(facetStr,
- SchemaSymbols::fgELT_ANNOTATION) == 0
- || XMLString::compareString(facetStr,
- SchemaSymbols::fgELT_SIMPLETYPE) == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
- }
- else {
- if (facets->containsKey(facetStr)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetStr);
- }
- else {
- fBuffer.set(attValue.rawBuffer(), attValueLen);
- const XMLCh* attVal = fBuffer.getRawBuffer();
- if (!XMLString::compareString(facetStr, SchemaSymbols::fgELT_WHITESPACE)
- && baseValidator->getType() != DatatypeValidator::String
- && XMLString::compareString(attVal, SchemaSymbols::fgWS_COLLAPSE) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::WS_CollapseExpected,
- attVal);
- }
- else {
- facets->put((void*) facetStr, new KVStringPair(facetStr, attVal));
- checkFixedFacet(content, facetStr, baseValidator, fixedFlag);
- }
- }
- }
- // REVISIT
- // check for annotation content - we are not checking whether the
- // return is empty or not. If not empty we should report an error
- checkContent(rootElem, XUtil::getFirstChildElement(content), true);
- }
- content = XUtil::getNextSiblingElement(content);
- } // end while
- if (!pattern.isEmpty()) {
- facets->put((void*) SchemaSymbols::fgELT_PATTERN,
- new KVStringPair(SchemaSymbols::fgELT_PATTERN, pattern.getRawBuffer()));
- }
- if (fixedFlag) {
- XMLString::binToText(fixedFlag, fixedFlagStr, 15, 10);
- facets->put((void*) SchemaSymbols::fgATT_FIXED,
- new KVStringPair(SchemaSymbols::fgATT_FIXED, fixedFlagStr));
- }
- int strId = fStringPool->addOrFind(getQualifiedName(typeNameIndex));
- const XMLCh* qualifiedName = fStringPool->getValueForId(strId);
- try {
- DatatypeValidator* newValidator =
- fDatatypeRegistry->getDatatypeValidator(qualifiedName);
- if (newValidator == 0) {
- fDatatypeRegistry->createDatatypeValidator
- (qualifiedName, baseValidator, facets, enums, false, finalSet);
- }
- }
- catch (const XMLException& excep) {
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::DisplayErrorMessage, excep.getMessage());
- }
- catch(...) {
- reportSchemaError(XMLUni::fgXMLErrDomain,
- XMLErrs::DatatypeValidatorCreationError, typeName);
- }
- return resetCurrentTypeNameStack(strId);
- }
- int TraverseSchema::traverseByUnion(const DOM_Element& rootElem,
- const DOM_Element& contentElem,
- const int typeNameIndex,
- const int finalSet,
- int baseRefContext) {
- int size = 1;
- DOM_Element content = contentElem;
- const XMLCh* const typeName =
- fStringPool->getValueForId(typeNameIndex);
- const XMLCh* baseTypeName = getElementAttValue(content,
- SchemaSymbols::fgATT_MEMBERTYPES);
- DatatypeValidator* baseValidator = 0;
- RefVectorOf<DatatypeValidator>* validators =
- new RefVectorOf<DatatypeValidator>(4, false);
- Janitor<DVRefVector> janValidators(validators);
- if (XUtil::getNextSiblingElement(content) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::SimpleTypeContentError);
- }
- if (XMLString::stringLen(baseTypeName)) { //base was provided - get proper validator.
- XMLStringTokenizer unionMembers(baseTypeName);
- int tokCount = unionMembers.countTokens();
- for (int i = 0; i < tokCount; i++) {
- const XMLCh* typeName = unionMembers.nextToken();
- baseValidator = findDTValidator(rootElem, typeName, SchemaSymbols::UNION);
- if (baseValidator == 0) {
- return resetCurrentTypeNameStack(-1);
- }
- validators->addElement(baseValidator);
- }
- content = checkContent(rootElem, XUtil::getFirstChildElement(content), true);
- }
- else { // must 'see' <simpleType>
- content = checkContent(rootElem, XUtil::getFirstChildElement(content), false);
- if (content == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ExpectedSimpleTypeInUnion, typeName);
- return resetCurrentTypeNameStack(-1);
- }
- if (!content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
- return resetCurrentTypeNameStack(-1);
- }
- }
- // process union content of simpleType children if any
- while (content != 0) {
- if (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
- baseValidator = checkForSimpleTypeValidator(content, baseRefContext | SchemaSymbols::UNION);
- if (baseValidator == 0) {
- return resetCurrentTypeNameStack(-1);
- }
- validators->addElement(baseValidator);
- }
- else {
- // REVISIT - should we break. For now, we will continue and move to
- // the next sibling
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ListUnionRestrictionError, typeName);
- }
- content = XUtil::getNextSiblingElement(content);
- } // end while
- int strId = fStringPool->addOrFind(getQualifiedName(typeNameIndex));
- const XMLCh* qualifiedName = fStringPool->getValueForId(strId);
- try {
- DatatypeValidator* newValidator =
- fDatatypeRegistry->getDatatypeValidator(qualifiedName);
- if (newValidator == 0) {
- if (fDatatypeRegistry->createDatatypeValidator(
- qualifiedName, validators, finalSet) != 0) {
- janValidators.orphan();
- }
- }
- }
- catch (const XMLException& excep) {
- janValidators.orphan();
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::DisplayErrorMessage, excep.getMessage());
- }
- catch(...) {
- janValidators.orphan();
- reportSchemaError(XMLUni::fgXMLErrDomain,
- XMLErrs::DatatypeValidatorCreationError, typeName);
- }
- return resetCurrentTypeNameStack(strId);
- }
- /**
- * Traverse SimpleContent Declaration
- *
- * <simpleContent
- * id = ID
- * {any attributes with non-schema namespace...}>
- *
- * Content: (annotation? , (restriction | extension))
- * </simpleContent>
- *
- * <restriction
- * base = QNAME
- * id = ID
- * {any attributes with non-schema namespace...}>
- *
- * Content: (annotation?, (simpleType?, (minExclusive | minInclusive
- * | maxExclusive | maxInclusive | totalDigits | fractionDigits
- * | length | minLength | maxLength | enumeration | pattern
- * | whiteSpace)*)?, ((attribute | attributeGroup)* , anyAttribute?))
- * </restriction>
- *
- * <extension
- * base = QNAME
- * id = ID
- * {any attributes with non-schema namespace...}>
- * Content: (annotation? , ((attribute | attributeGroup)* , anyAttribute?))
- * </extension>
- *
- */
- void TraverseSchema::traverseSimpleContentDecl(const XMLCh* const typeName,
- const DOM_Element& contentDecl,
- ComplexTypeInfo* const typeInfo)
- {
- // -----------------------------------------------------------------------
- // Check Attributes
- // -----------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(contentDecl, scope, this);
- // -----------------------------------------------------------------------
- // Set the content type to be simple, and initialize content spec handle
- // -----------------------------------------------------------------------
- typeInfo->setContentType(SchemaElementDecl::Simple);
- DOM_Element simpleContent =
- checkContent(contentDecl, XUtil::getFirstChildElement(contentDecl),false);
- // If there are no children, return
- if (simpleContent == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- fAttributeCheck.checkAttributes(simpleContent, scope, this);
- // -----------------------------------------------------------------------
- // The content should be either "restriction" or "extension"
- // -----------------------------------------------------------------------
- DOMString contentName = simpleContent.getLocalName();
- if (contentName.equals(SchemaSymbols::fgATTVAL_RESTRICTION)) {
- typeInfo->setDerivedBy(SchemaSymbols::RESTRICTION);
- }
- else if (contentName.equals(SchemaSymbols::fgATTVAL_EXTENSION)) {
- typeInfo->setDerivedBy(SchemaSymbols::EXTENSION);
- }
- else {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContent);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- // -----------------------------------------------------------------------
- // Handle the base type name
- // -----------------------------------------------------------------------
- const XMLCh* baseName =
- getElementAttValue(simpleContent, SchemaSymbols::fgATT_BASE);
- if (XMLString::stringLen(baseName) == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- const XMLCh* prefix = getPrefix(baseName);
- const XMLCh* localPart = getLocalPart(baseName);
- const XMLCh* uri = resolvePrefixToURI(prefix);
- DatatypeValidator* baseValidator = getDatatypeValidator(uri, localPart);
- if (baseValidator != 0) {
- // check that the simpleType does not preclude derivation by extension
- if ((baseValidator->getFinalSet() & SchemaSymbols::EXTENSION) == typeInfo->getDerivedBy()) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DisallowedSimpleTypeExtension,
- baseName, typeName);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- typeInfo->setBaseComplexTypeInfo(0);
- typeInfo->setBaseDatatypeValidator(baseValidator);
- }
- else {
- // check for 'anyType'
- if (!XMLString::compareString(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)
- && !XMLString::compareString(localPart, SchemaSymbols::fgATTVAL_ANYTYPE)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- processBaseTypeInfo(baseName, localPart, uri, typeInfo);
- }
- // check that the base isn't a complex type with complex content
- // and that derivation method is not included in 'final'
- ComplexTypeInfo* baseTypeInfo = typeInfo->getBaseComplexTypeInfo();
- if (baseTypeInfo) {
- if (baseTypeInfo->getContentType() != SchemaElementDecl::Simple) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidSimpleContentBase, baseName);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- if ((baseTypeInfo->getFinalSet() & typeInfo->getDerivedBy()) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::ForbiddenDerivation, baseName);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- }
- // -----------------------------------------------------------------------
- // Process the content of the derivation
- // -----------------------------------------------------------------------
- //Skip over any annotations in the restriction or extension elements
- DOM_Element content = checkContent(simpleContent,
- XUtil::getFirstChildElement(simpleContent), true);
- if (typeInfo->getDerivedBy() == SchemaSymbols::RESTRICTION) {
- //Schema Spec: 5.11: Complex Type Definition Properties Correct: 2
- if (typeInfo->getBaseDatatypeValidator() != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexTypeBase, baseName);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- else {
- 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 (content.getLocalName().equals(SchemaSymbols::fgELT_SIMPLETYPE)) {
- int simpleTypeNameIndex = traverseSimpleTypeDecl(content);
- if (simpleTypeNameIndex !=-1) {
- DatatypeValidator* simpleTypeDV =
- fDatatypeRegistry->getDatatypeValidator(fStringPool->getValueForId(simpleTypeNameIndex));
- // Check that the simpleType validator is validly derived
- // from base
- DatatypeValidator* baseDV = typeInfo->getBaseDatatypeValidator();
- if (baseDV && !baseDV->isSubstitutableBy(simpleTypeDV)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidContentRestriction);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- typeInfo->setBaseDatatypeValidator(simpleTypeDV);
- content = XUtil::getNextSiblingElement(content);
- }
- else {
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- }
- // ---------------------------------------------------------------
- // Build up the facet info
- // ---------------------------------------------------------------
- RefHashTableOf<KVStringPair>* facets = 0;
- RefVectorOf<XMLCh>* enums = 0;
- XMLBuffer pattern;
- const XMLCh* facetName;
- XMLCh fixedFlagStr[16];
- unsigned int fixedFlag = 0;
- int facetId;
- bool isFirstPattern = true;
- while (content != 0) {
- fBuffer.set(content.getLocalName().rawBuffer(), content.getLocalName().length());
- facetId = fStringPool->addOrFind(fBuffer.getRawBuffer());
- facetName = fStringPool->getValueForId(facetId);
- // if not a valid facet, break from the loop
- if (!isValidFacet(SchemaSymbols::fgELT_SIMPLECONTENT, facetName)) {
- break;
- }
- if (content.getNodeType() == DOM_Node::ELEMENT_NODE) {
- fAttributeCheck.checkAttributes(content, scope, this);
- DOMString attValue =
- content.getAttribute(SchemaSymbols::fgATT_VALUE);
- if (facets == 0) {
- facets = new RefHashTableOf<KVStringPair>(29, true);
- }
- fBuffer.set(attValue.rawBuffer(), attValue.length());
- if (XMLString::compareString(facetName,
- SchemaSymbols::fgELT_ENUMERATION) == 0) {
- if (!enums) {
- enums = new RefVectorOf<XMLCh>(8, true);
- }
- enums->addElement(XMLString::replicate(fBuffer.getRawBuffer()));
- }
- else if (XMLString::compareString(facetName,
- SchemaSymbols::fgELT_PATTERN) == 0) {
- if (isFirstPattern) { // fBuffer.isEmpty() - overhead call
- isFirstPattern = false;
- pattern.set(fBuffer.getRawBuffer());
- }
- else { //datatypes: 5.2.4 pattern
- pattern.append(chPipe);
- pattern.append(fBuffer.getRawBuffer());
- }
- }
- else {
- if (facets->containsKey(facetName)) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::DuplicateFacet, facetName);
- }
- else {
- facets->put((void*) facetName,
- new KVStringPair(facetName,fBuffer.getRawBuffer()));
- checkFixedFacet(content, facetName, typeInfo->getBaseDatatypeValidator(), fixedFlag);
- }
- }
- }
- content = XUtil::getNextSiblingElement(content);
- }
- if (facets) {
- if (!pattern.isEmpty()) {
- facets->put
- (
- (void*) SchemaSymbols::fgELT_PATTERN,
- new KVStringPair
- (
- SchemaSymbols::fgELT_PATTERN,
- pattern.getRawBuffer()
- )
- );
- }
- if (fixedFlag) {
- XMLString::binToText(fixedFlag, fixedFlagStr, 15, 10);
- facets->put((void*) SchemaSymbols::fgATT_FIXED,
- new KVStringPair(SchemaSymbols::fgATT_FIXED, fixedFlagStr));
- }
- int nameId = fStringPool->addOrFind(getQualifiedName(fStringPool->addOrFind(typeName)));
- const XMLCh* qualifiedName = fStringPool->getValueForId(nameId);
- try {
- typeInfo->setDatatypeValidator
- (
- fDatatypeRegistry->createDatatypeValidator
- (
- qualifiedName,
- typeInfo->getBaseDatatypeValidator(),
- facets, enums, false, 0
- )
- );
- }
- catch (const XMLException& excep) {
- reportSchemaError(XMLUni::fgValidityDomain, XMLValid::DisplayErrorMessage, excep.getMessage());
- }
- catch(...) {
- reportSchemaError(XMLUni::fgXMLErrDomain,
- XMLErrs::DatatypeValidatorCreationError, typeName);
- }
- }
- else {
- typeInfo->setDatatypeValidator(
- typeInfo->getBaseDatatypeValidator());
- }
- }
- else {
- 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
- // -----------------------------------------------------------------------
- if (content != 0 && isAttrOrAttrGroup(content)) {
- processAttributes(content, baseName, localPart, uri, typeInfo);
- }
- if (XUtil::getNextSiblingElement(simpleContent) != 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildInSimpleContent);
- }
- } // End of function traverseSimpleContentDecl
- /**
- * Traverse complexContent Declaration
- *
- * <complexContent
- * id = ID
- * mixed = boolean
- * {any attributes with non-schema namespace...}>
- *
- * Content: (annotation? , (restriction | extension))
- * </complexContent>
- *
- * <restriction
- * base = QNAME
- * id = ID
- * {any attributes with non-schema namespace...}>
- *
- * Content: (annotation? , (group | all | choice | sequence)?,
- * ((attribute | attributeGroup)* , anyAttribute?))
- * </restriction>
- *
- * <extension
- * base = QNAME
- * id = ID
- * {any attributes with non-schema namespace...}>
- * Content: (annotation? , (group | all | choice | sequence)?,
- * ((attribute | attributeGroup)* , anyAttribute?))
- * </extension>
- */
- void TraverseSchema::traverseComplexContentDecl(const XMLCh* const typeName,
- const DOM_Element& contentDecl,
- ComplexTypeInfo* const typeInfo,
- const bool isMixed)
- {
- // ------------------------------------------------------------------
- // Check attributes
- // ------------------------------------------------------------------
- unsigned short scope = GeneralAttributeCheck::LocalContext;
- fAttributeCheck.checkAttributes(contentDecl, scope, this);
- // -----------------------------------------------------------------------
- // 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);
- bool mixedContent = isMixed;
- if (mixed) {
- if (!XMLString::compareString(mixed, SchemaSymbols::fgATTVAL_TRUE)
- || !XMLString::compareString(mixed, fgValueOne)) {
- mixedContent = true;
- }
- else if (!XMLString::compareString(mixed, SchemaSymbols::fgATTVAL_FALSE)
- || !XMLString::compareString(mixed, fgValueZero)) {
- mixedContent = false;
- }
- }
- // -----------------------------------------------------------------------
- // Since the type must have complex content, set the simple type validators
- // to null
- // -----------------------------------------------------------------------
- typeInfo->setDatatypeValidator(0);
- typeInfo->setBaseDatatypeValidator(0);
- DOM_Element complexContent =
- checkContent(contentDecl,XUtil::getFirstChildElement(contentDecl),false);
- // If there are no children, return
- if (complexContent == 0) {
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- // -----------------------------------------------------------------------
- // The content should be either "restriction" or "extension"
- // -----------------------------------------------------------------------
- DOMString complexContentName = complexContent.getLocalName();
- if (complexContentName.equals(SchemaSymbols::fgELT_RESTRICTION)) {
- typeInfo->setDerivedBy(SchemaSymbols::RESTRICTION);
- }
- else if (complexContentName.equals(SchemaSymbols::fgELT_EXTENSION)) {
- typeInfo->setDerivedBy(SchemaSymbols::EXTENSION);
- }
- else {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::InvalidComplexContent);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- // -----------------------------------------------------------------------
- // Handle the base type name
- // -----------------------------------------------------------------------
- const XMLCh* baseName =
- getElementAttValue(complexContent, SchemaSymbols::fgATT_BASE);
- if (XMLString::stringLen(baseName) == 0) {
- reportSchemaError(XMLUni::fgXMLErrDomain, XMLErrs::UnspecifiedBase);
- throw TraverseSchema::InvalidComplexTypeInfo;
- }
- const XMLCh* prefix = getPrefix(baseName);
- const XMLCh* localPart = getLocalPart(baseName);
- const XMLCh* uri = resolvePrefixToURI(prefix);
- bool isBaseAnyType = false;
- // -------------------------------------------------------------
- // check if the base is "anyType"
- // -------------------------------------------------------------
- if (XMLString::compareString(uri, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) == 0 &&
- XMLString::compareString(localPart, SchemaSymbols::fgATTVAL_ANYTYPE) == 0) {
- isBaseAnyType = true;
- }
- else {
- processBaseTypeInfo(baseName, localPart, uri, typeInfo);
- //Check that the base is a complex type