blob: cd2198d17d5fbd9068792b45b9b6fc0be1b7343c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id$
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/schema/TraverseSchema.hpp>
#include <xercesc/framework/XMLEntityHandler.hpp>
#include <xercesc/framework/XMLValidityCodes.hpp>
#include <xercesc/validators/schema/identity/IC_Key.hpp>
#include <xercesc/validators/schema/identity/IC_KeyRef.hpp>
#include <xercesc/validators/schema/identity/IC_Unique.hpp>
#include <xercesc/validators/schema/identity/IC_Field.hpp>
#include <xercesc/validators/schema/identity/IC_Selector.hpp>
#include <xercesc/validators/schema/identity/XercesXPath.hpp>
#include <xercesc/util/XMLStringTokenizer.hpp>
#include <xercesc/validators/schema/XUtil.hpp>
#include <xercesc/validators/common/GrammarResolver.hpp>
#include <xercesc/internal/XMLReader.hpp>
#include <xercesc/validators/schema/ComplexTypeInfo.hpp>
#include <xercesc/validators/schema/NamespaceScope.hpp>
#include <xercesc/validators/schema/SchemaAttDefList.hpp>
#include <xercesc/internal/XMLScanner.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/framework/URLInputSource.hpp>
#include <xercesc/framework/XMLGrammarPool.hpp>
#include <xercesc/framework/XMLSchemaDescription.hpp>
#include <xercesc/validators/schema/identity/XPathException.hpp>
#include <xercesc/validators/schema/GeneralAttributeCheck.hpp>
#include <xercesc/validators/schema/XercesGroupInfo.hpp>
#include <xercesc/validators/schema/XercesAttGroupInfo.hpp>
#include <xercesc/validators/schema/XSDLocator.hpp>
#include <xercesc/validators/schema/XSDDOMParser.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/dom/DOMText.hpp>
#include <xercesc/dom/impl/XSDElementNSImpl.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/NumberFormatException.hpp>
#include <xercesc/util/XMLEntityResolver.hpp>
#include <xercesc/util/XMLUri.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/internal/XSAXMLScanner.hpp>
namespace XERCES_CPP_NAMESPACE {
// ---------------------------------------------------------------------------
// TraverseSchema: Local declaration
// ---------------------------------------------------------------------------
// This helper class will handle the parsing of namespace prefixes for a given DOMElement, and its winding back
class NamespaceScopeManager
{
public:
NamespaceScopeManager(const DOMElement* const node, SchemaInfo* info, TraverseSchema* traverser)
{
fScopeAdded=node?traverser->retrieveNamespaceMapping(node):false;
fSchemaInfo=info;
}
~NamespaceScopeManager()
{
if(fScopeAdded)
fSchemaInfo->getNamespaceScope()->decreaseDepth();
}
protected:
bool fScopeAdded;
SchemaInfo* fSchemaInfo;
};
// ---------------------------------------------------------------------------
// TraverseSchema: Static member data
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// TraverseSchema: Local const data
// ---------------------------------------------------------------------------
static const XMLCh fgAnonSNamePrefix[] =
{
chUnderscore, chUnderscore, chLatin_A, chLatin_n, chLatin_o, chLatin_n, chLatin_S, chNull
};
static const XMLCh fgAnonCNamePrefix[] =
{
chUnderscore, chUnderscore, chLatin_A, chLatin_n, chLatin_o, chLatin_n, chLatin_C, chNull
};
static const XMLCh fgUnbounded[] =
{
chLatin_u, chLatin_n, chLatin_b, chLatin_o, chLatin_u, chLatin_n, chLatin_d,
chLatin_e, chLatin_d, chNull
};
static const XMLCh fgValueOne[] =
{
chDigit_1, chNull
};
static const XMLCh fgValueZero[] =
{
chDigit_0, chNull
};
static const XMLCh* fgIdentityConstraints[] =
{
SchemaSymbols::fgELT_UNIQUE,
SchemaSymbols::fgELT_KEY,
SchemaSymbols::fgELT_KEYREF
};
static const XMLCh fgSynthetic_Annotation[] =
{
chLatin_S, chLatin_y, chLatin_n, chLatin_t, chLatin_h, chLatin_e, chLatin_t
, chLatin_i, chLatin_c, chUnderscore
, chLatin_A, chLatin_n, chLatin_n, chLatin_o, chLatin_t, chLatin_a, chLatin_t
, chLatin_i, chLatin_o, chLatin_n, chNull
};
// Flags for global declaration
enum {
ENUM_ELT_SIMPLETYPE,
ENUM_ELT_COMPLEXTYPE,
ENUM_ELT_ELEMENT,
ENUM_ELT_ATTRIBUTE,
ENUM_ELT_ATTRIBUTEGROUP,
ENUM_ELT_GROUP,
ENUM_ELT_SIZE
};
typedef JanitorMemFunCall<TraverseSchema> CleanupType;
// ---------------------------------------------------------------------------
// TraverseSchema: Constructors and Destructor
// ---------------------------------------------------------------------------
TraverseSchema::TraverseSchema( DOMElement* const schemaRoot
, XMLStringPool* const uriStringPool
, SchemaGrammar* const schemaGrammar
, GrammarResolver* const grammarResolver
, RefHash2KeysTableOf<SchemaInfo>* cachedSchemaInfoList
, RefHash2KeysTableOf<SchemaInfo>* schemaInfoList
, XMLScanner* const xmlScanner
, const XMLCh* const schemaURL
, XMLEntityHandler* const entityHandler
, XMLErrorReporter* const errorReporter
, MemoryManager* const manager
, bool multipleImport)
: fFullConstraintChecking(false)
, fTargetNSURI(-1)
, fEmptyNamespaceURI(-1)
, fCurrentScope(Grammar::TOP_LEVEL_SCOPE)
, fScopeCount(schemaGrammar->getScopeCount ())
, fAnonXSTypeCount(schemaGrammar->getAnonTypeCount ())
, fCircularCheckIndex(0)
, fTargetNSURIString(0)
, fDatatypeRegistry(0)
, fGrammarResolver(grammarResolver)
, fSchemaGrammar(schemaGrammar)
, fEntityHandler(entityHandler)
, fErrorReporter(errorReporter)
, fURIStringPool(uriStringPool)
, fStringPool(0)
, fBuffer(1023, manager)
, fScanner(xmlScanner)
, fAttributeDeclRegistry(0)
, fComplexTypeRegistry(0)
, fGroupRegistry(0)
, fAttGroupRegistry(0)
, fIC_ElementsNS(0)
, fPreprocessedNodes(0)
, fSchemaInfo(0)
, fCurrentGroupInfo(0)
, fCurrentAttGroupInfo(0)
, fCurrentComplexType(0)
, fCurrentTypeNameStack(0)
, fCurrentGroupStack(0)
, fIC_Elements(0)
, fDeclStack(0)
, fGlobalDeclarations(0)
, fNonXSAttList(0)
, fImportedNSList(0)
, fIC_NodeListNS(0)
, fNotationRegistry(0)
, fRedefineComponents(0)
, fIdentityConstraintNames(0)
, fValidSubstitutionGroups(0)
, fSchemaInfoList(schemaInfoList)
, fCachedSchemaInfoList (cachedSchemaInfoList)
, fParser(0)
, fLocator(0)
, fMemoryManager(manager)
, fGrammarPoolMemoryManager(fGrammarResolver->getGrammarPoolMemoryManager())
, fAnnotation(0)
, fAttributeCheck(manager)
{
CleanupType cleanup(this, &TraverseSchema::cleanUp);
try {
if (fGrammarResolver && schemaRoot && fURIStringPool) {
init();
if (multipleImport)
{
// If we are working on an existing schema, do some
// intitialization that is otherwise done by preprocessSchema.
//
fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry();
fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry();
fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry();
fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry();
fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups();
}
preprocessSchema(schemaRoot, schemaURL, multipleImport);
doTraverseSchema(schemaRoot);
// Store the scope and anon type counts in case we need to add
// more to this grammar (multi-import case). schemaGrammar and
// fSchemaGrammar should be the same here.
//
fSchemaGrammar->setScopeCount (fScopeCount);
fSchemaGrammar->setAnonTypeCount (fAnonXSTypeCount);
}
}
catch(const OutOfMemoryException&)
{
cleanup.release();
throw;
}
cleanup.release();
}
TraverseSchema::~TraverseSchema()
{
cleanUp();
}
// ---------------------------------------------------------------------------
// TraverseSchema: Traversal methods
// ---------------------------------------------------------------------------
void TraverseSchema::doTraverseSchema(const DOMElement* const schemaRoot) {
// process children nodes
processChildren(schemaRoot);
// Handle identity constraints - keyref
if (fIC_ElementsNS && fIC_ElementsNS->containsKey(fTargetNSURIString)) {
fIC_Elements = fIC_ElementsNS->get(fTargetNSURIString);
XMLSize_t icListSize = fIC_Elements->size();
for (XMLSize_t i=0; i < icListSize; i++) {
SchemaElementDecl* curElem = fIC_Elements->elementAt(i);
ValueVectorOf<DOMElement*>* icNodes = fIC_NodeListNS->get(curElem);
XMLSize_t icNodesSize = icNodes->size();
for (XMLSize_t j = 0; j < icNodesSize; j++) {
traverseKeyRef(icNodes->elementAt(j), curElem);
}
}
}
if (fScanner->getValidateAnnotations() && !fSchemaGrammar->getAnnotations()->isEmpty())
{
validateAnnotations();
}
fSchemaInfo->setProcessed();
}
void TraverseSchema::preprocessSchema(DOMElement* const schemaRoot,
const XMLCh* const schemaURL,
bool multipleImport) {
if (!multipleImport) {
// Make sure namespace binding is defaulted
const XMLCh* rootPrefix = schemaRoot->getPrefix();
if (rootPrefix == 0 || !*rootPrefix) {
const XMLCh* xmlnsStr = schemaRoot->getAttribute(XMLUni::fgXMLNSString);
if (!xmlnsStr || !*xmlnsStr) {
schemaRoot->setAttribute(XMLUni::fgXMLNSString, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
}
}
// Set schemaGrammar data and add it to GrammarResolver
// For complex type registry, attribute decl registry , group/attGroup
// and namespace mapping, needs to check whether the passed in
// Grammar was a newly instantiated one.
fComplexTypeRegistry = fSchemaGrammar->getComplexTypeRegistry();
if (fComplexTypeRegistry == 0 ) {
fComplexTypeRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf<ComplexTypeInfo>(29, fGrammarPoolMemoryManager);
fSchemaGrammar->setComplexTypeRegistry(fComplexTypeRegistry);
}
fGroupRegistry = fSchemaGrammar->getGroupInfoRegistry();
if (fGroupRegistry == 0 ) {
fGroupRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf<XercesGroupInfo>(13, fGrammarPoolMemoryManager);
fSchemaGrammar->setGroupInfoRegistry(fGroupRegistry);
}
fAttGroupRegistry = fSchemaGrammar->getAttGroupInfoRegistry();
if (fAttGroupRegistry == 0 ) {
fAttGroupRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf<XercesAttGroupInfo>(13, fGrammarPoolMemoryManager);
fSchemaGrammar->setAttGroupInfoRegistry(fAttGroupRegistry);
}
fAttributeDeclRegistry = fSchemaGrammar->getAttributeDeclRegistry();
if (fAttributeDeclRegistry == 0) {
fAttributeDeclRegistry = new (fGrammarPoolMemoryManager) RefHashTableOf<XMLAttDef>(29, fGrammarPoolMemoryManager);
fSchemaGrammar->setAttributeDeclRegistry(fAttributeDeclRegistry);
}
fValidSubstitutionGroups = fSchemaGrammar->getValidSubstitutionGroups();
if (!fValidSubstitutionGroups) {
fValidSubstitutionGroups = new (fGrammarPoolMemoryManager) RefHash2KeysTableOf<ElemVector>(29, fGrammarPoolMemoryManager);
fSchemaGrammar->setValidSubstitutionGroups(fValidSubstitutionGroups);
}
//Retrieve the targetnamespace URI information
const XMLCh* targetNSURIStr = schemaRoot->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
fSchemaGrammar->setTargetNamespace(targetNSURIStr);
fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
fTargetNSURIString = fSchemaGrammar->getTargetNamespace();
fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString);
XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) fSchemaGrammar->getGrammarDescription();
gramDesc->setTargetNamespace(fTargetNSURIString);
fGrammarResolver->putGrammar(fSchemaGrammar);
}
else {
fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
fTargetNSURIString = fSchemaGrammar->getTargetNamespace();
fTargetNSURI = fURIStringPool->addOrFind(fTargetNSURIString);
}
SchemaInfo* currInfo = new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI,
0,
schemaURL,
fTargetNSURIString, schemaRoot,
fScanner,
fGrammarPoolMemoryManager);
currInfo->getNamespaceScope()->reset(fEmptyNamespaceURI);
// Add mapping for the xml prefix
currInfo->getNamespaceScope()->addPrefix(XMLUni::fgXMLString, fURIStringPool->addOrFind(XMLUni::fgXMLURIName));
if (fSchemaInfo)
fSchemaInfo->addSchemaInfo(currInfo, SchemaInfo::IMPORT);
addImportedNS(currInfo->getTargetNSURI());
fSchemaInfo = currInfo;
fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(), fSchemaInfo->getTargetNSURI(), fSchemaInfo);
fSchemaInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE);
traverseSchemaHeader(schemaRoot);
// preprocess chidren
preprocessChildren(schemaRoot);
}
void TraverseSchema::traverseSchemaHeader(const DOMElement* const schemaRoot) {
// Make sure that the root element is <xsd:schema>
if (!XMLString::equals(schemaRoot->getLocalName(), SchemaSymbols::fgELT_SCHEMA)) {
reportSchemaError(schemaRoot, XMLUni::fgXMLErrDomain, XMLErrs::InvalidXMLSchemaRoot);
}
// Make sure that the targetNamespace value is not empty string
checkForEmptyTargetNamespace(schemaRoot);
// -----------------------------------------------------------------------
// Check Attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
schemaRoot, GeneralAttributeCheck::E_Schema, this
, true, fSchemaInfo->getNonXSAttList()
);
retrieveNamespaceMapping(schemaRoot);
// Add mapping for the default namespace
if ((!fTargetNSURIString || !*fTargetNSURIString) && schemaRoot->getAttributeNode(XMLUni::fgXMLNSString)==NULL)
fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgZeroLenString, fEmptyNamespaceURI);
unsigned short elemAttrDefaultQualified = 0;
if (XMLString::equals(schemaRoot->getAttribute(SchemaSymbols::fgATT_ELEMENTFORMDEFAULT),
SchemaSymbols::fgATTVAL_QUALIFIED)) {
elemAttrDefaultQualified |= Elem_Def_Qualified;
}
if (XMLString::equals(schemaRoot->getAttribute(SchemaSymbols::fgATT_ATTRIBUTEFORMDEFAULT),
SchemaSymbols::fgATTVAL_QUALIFIED)) {
elemAttrDefaultQualified |= Attr_Def_Qualified;
}
fSchemaInfo->setElemAttrDefaultQualified(elemAttrDefaultQualified);
fSchemaInfo->setBlockDefault(parseBlockSet(schemaRoot, ES_Block, true));
fSchemaInfo->setFinalDefault(parseFinalSet(schemaRoot, ECS_Final, true));
}
XSAnnotation*
TraverseSchema::traverseAnnotationDecl(const DOMElement* const annotationElem,
ValueVectorOf<DOMNode*>* const nonXSAttList,
const bool topLevel) {
NamespaceScopeManager nsMgr(annotationElem, fSchemaInfo, this);
// -----------------------------------------------------------------------
// Check Attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
annotationElem, GeneralAttributeCheck::E_Annotation, this, topLevel
);
const XMLCh* contents = 0;
DOMElement* child = XUtil::getFirstChildElement(annotationElem);
if (child) {
for (;
child != 0;
child = XUtil::getNextSiblingElement(child)) {
const XMLCh* name = child->getLocalName();
if (XMLString::equals(name, SchemaSymbols::fgELT_APPINFO)) {
DOMNode* textContent = child->getFirstChild();
if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE)
contents = ((DOMText*) textContent)->getData();
fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::E_Appinfo, this);
}
else if (XMLString::equals(name, SchemaSymbols::fgELT_DOCUMENTATION)) {
DOMNode* textContent = child->getFirstChild();
if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE)
contents = ((DOMText*) textContent)->getData();
fAttributeCheck.checkAttributes(child, GeneralAttributeCheck::E_Documentation, this);
}
else {
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAnnotationContent);
}
}
}
else
{
// If the Annotation has no children, get the text directly
DOMNode* textContent = annotationElem->getFirstChild();
if (textContent && textContent->getNodeType() == DOMNode::TEXT_NODE)
contents = ((DOMText*) textContent)->getData();
}
if (contents && !fScanner->getIgnoreAnnotations())
{
XSAnnotation* theAnnotation = 0;
XMLSize_t nonXSAttSize = nonXSAttList->size();
if (nonXSAttSize)
{
int annotTokenStart = XMLString::patternMatch(
contents, SchemaSymbols::fgELT_ANNOTATION);
if (annotTokenStart == -1) // something is wrong
return 0;
// set annotation element
fBuffer.set(contents, annotTokenStart + 10);
for (XMLSize_t i=0; i<nonXSAttSize; i++)
{
DOMNode* attNode = nonXSAttList->elementAt(i);
if (!XMLString::equals(
annotationElem->getAttributeNS(
attNode->getNamespaceURI(), attNode->getLocalName())
, XMLUni::fgZeroLenString)
)
{
continue;
}
fBuffer.append(chSpace);
fBuffer.append(attNode->getNodeName());
fBuffer.append(chEqual);
fBuffer.append(chDoubleQuote);
processAttValue(attNode->getNodeValue(), fBuffer);
fBuffer.append(chDoubleQuote);
}
// add remaining annotation content
fBuffer.append(contents + annotTokenStart + 10);
theAnnotation = new (fGrammarPoolMemoryManager) XSAnnotation(fBuffer.getRawBuffer(), fGrammarPoolMemoryManager);
}
else
{
theAnnotation = new (fGrammarPoolMemoryManager) XSAnnotation(contents, fGrammarPoolMemoryManager);
}
/***
* set line, col and systemId info
***/
theAnnotation->setLineCol(
((XSDElementNSImpl*)annotationElem)->getLineNo()
, ((XSDElementNSImpl*)annotationElem)->getColumnNo()
);
theAnnotation->setSystemId(fSchemaInfo->getCurrentSchemaURL());
return theAnnotation;
}
return 0;
}
/**
* Traverse include
*
* <include
* id = ID
* schemaLocation = anyURI
* {any attributes with non-schema namespace . . .}>
* Content: (annotation?)
* </include>
*/
void TraverseSchema::preprocessInclude(const DOMElement* const elem) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// -----------------------------------------------------------------------
// Check attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
elem, GeneralAttributeCheck::E_Include, this, true, fNonXSAttList);
// -----------------------------------------------------------------------
// First, handle any ANNOTATION declaration
// -----------------------------------------------------------------------
if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0)
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected);
if (fAnnotation)
fSchemaGrammar->addAnnotation(fAnnotation);
else if (fScanner->getGenerateSyntheticAnnotations() && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
fSchemaGrammar->addAnnotation(fAnnotation);
}
// -----------------------------------------------------------------------
// Get 'schemaLocation' attribute
// -----------------------------------------------------------------------
const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION, DatatypeValidator::AnyURI);
if (!schemaLocation || !*schemaLocation) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNoSchemaLocation, SchemaSymbols::fgELT_INCLUDE);
return;
}
// ------------------------------------------------------------------
// Resolve schema location
// ------------------------------------------------------------------
fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0,
((XSDElementNSImpl*) elem)->getLineNo(),
((XSDElementNSImpl*) elem)->getColumnNo());
InputSource* srcToFill = resolveSchemaLocation(schemaLocation,
XMLResourceIdentifier::SchemaInclude);
Janitor<InputSource> janSrc(srcToFill);
// Nothing to do
if (!srcToFill) {
return;
}
const XMLCh* includeURL = srcToFill->getSystemId();
SchemaInfo* includeSchemaInfo = fCachedSchemaInfoList->get(includeURL, fTargetNSURI);
if (!includeSchemaInfo && fSchemaInfoList != fCachedSchemaInfoList)
includeSchemaInfo = fSchemaInfoList->get(includeURL, fTargetNSURI);
if (includeSchemaInfo) {
fSchemaInfo->addSchemaInfo(includeSchemaInfo, SchemaInfo::INCLUDE);
return;
}
// ------------------------------------------------------------------
// Parse input source
// ------------------------------------------------------------------
if (!fParser)
fParser = new (fGrammarPoolMemoryManager) XSDDOMParser(0, fGrammarPoolMemoryManager, 0);
fParser->setValidationScheme(XercesDOMParser::Val_Never);
fParser->setDoNamespaces(true);
fParser->setUserEntityHandler(fEntityHandler);
fParser->setUserErrorReporter(fErrorReporter);
// Should just issue warning if the schema is not found
bool flag = srcToFill->getIssueFatalErrorIfNotFound();
srcToFill->setIssueFatalErrorIfNotFound(false);
fParser->parse(*srcToFill);
// Reset the InputSource
srcToFill->setIssueFatalErrorIfNotFound(flag);
if (fParser->getSawFatal() && fScanner->getExitOnFirstFatal())
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError);
// ------------------------------------------------------------------
// Get root element
// ------------------------------------------------------------------
DOMDocument* document = fParser->getDocument();
if (document) {
DOMElement* root = document->getDocumentElement();
if (root) {
const XMLCh* targetNSURIString = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
// check to see if targetNameSpace is right
if (*targetNSURIString
&& !XMLString::equals(targetNSURIString,fTargetNSURIString)){
reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::IncludeNamespaceDifference,
schemaLocation, targetNSURIString);
return;
}
// if targetNamespace is empty, change it to includ'g schema
// targetNamespace
if (!*targetNSURIString && root->getAttributeNode(XMLUni::fgXMLNSString) == 0
&& fTargetNSURI != fEmptyNamespaceURI) {
root->setAttribute(XMLUni::fgXMLNSString, fTargetNSURIString);
}
// --------------------------------------------------------
// Update schema information with included schema
// --------------------------------------------------------
SchemaInfo* saveInfo = fSchemaInfo;
fSchemaInfo = new (fMemoryManager) SchemaInfo(0, 0, 0, fTargetNSURI,
0,
includeURL,
fTargetNSURIString, root,
fScanner,
fGrammarPoolMemoryManager);
fSchemaInfo->getNamespaceScope()->reset(fEmptyNamespaceURI);
// Add mapping for the xml prefix
fSchemaInfo->getNamespaceScope()->addPrefix(XMLUni::fgXMLString, fURIStringPool->addOrFind(XMLUni::fgXMLURIName));
fSchemaInfoList->put((void*) fSchemaInfo->getCurrentSchemaURL(),
fSchemaInfo->getTargetNSURI(), fSchemaInfo);
fPreprocessedNodes->put((void*) elem, fSchemaInfo);
saveInfo->addSchemaInfo(fSchemaInfo, SchemaInfo::INCLUDE);
traverseSchemaHeader(root);
preprocessChildren(root);
fSchemaInfo = saveInfo;
}
}
}
void TraverseSchema::traverseInclude(const DOMElement* const elem) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
SchemaInfo* includeInfo = fPreprocessedNodes->get(elem);
if (includeInfo) {
SchemaInfo* saveInfo = fSchemaInfo;
fSchemaInfo = includeInfo;
processChildren(includeInfo->getRoot());
fSchemaInfo = saveInfo;
}
}
/**
* Traverse import
*
* <import
* id = ID
* namespace = anyURI
* schemaLocation = anyURI
* {any attributes with non-schema namespace . . .}>
* Content: (annotation?)
* </import>
*/
void TraverseSchema::preprocessImport(const DOMElement* const elem) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// -----------------------------------------------------------------------
// Check attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
elem, GeneralAttributeCheck::E_Import, this, true, fNonXSAttList);
// -----------------------------------------------------------------------
// First, handle any ANNOTATION declaration
// -----------------------------------------------------------------------
if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0)
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected);
if (fAnnotation)
fSchemaGrammar->addAnnotation(fAnnotation);
else if (fScanner->getGenerateSyntheticAnnotations() && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
fSchemaGrammar->addAnnotation(fAnnotation);
}
// -----------------------------------------------------------------------
// Handle 'namespace' attribute
// -----------------------------------------------------------------------
const XMLCh* nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE, DatatypeValidator::AnyURI);
const XMLCh* nameSpaceValue = nameSpace ? nameSpace : XMLUni::fgZeroLenString;
if (XMLString::equals(nameSpaceValue, fTargetNSURIString)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Import_1_1);
return;
}
if (!*nameSpaceValue && fTargetNSURI == fEmptyNamespaceURI) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::Import_1_2);
return;
}
// ------------------------------------------------------------------
// Get 'schemaLocation' attribute
// ------------------------------------------------------------------
const XMLCh* schemaLocation = getElementAttValue(elem, SchemaSymbols::fgATT_SCHEMALOCATION, DatatypeValidator::AnyURI);
// ------------------------------------------------------------------
// Resolve namespace to a grammar
// ------------------------------------------------------------------
Grammar* aGrammar = 0;
{
XMLSchemaDescription* gramDesc =fGrammarResolver->getGrammarPool()->createSchemaDescription(nameSpaceValue);
Janitor<XMLSchemaDescription> janName(gramDesc);
gramDesc->setContextType(XMLSchemaDescription::CONTEXT_IMPORT);
gramDesc->setLocationHints(schemaLocation);
aGrammar = fGrammarResolver->getGrammar(gramDesc);
}
bool grammarFound = (aGrammar && (aGrammar->getGrammarType() == Grammar::SchemaGrammarType));
if (grammarFound) {
addImportedNS(fURIStringPool->addOrFind(nameSpaceValue));
}
// a bare <xs:import/> doesn't load anything
if(!schemaLocation && !nameSpace)
return;
// ------------------------------------------------------------------
// Resolve schema location
// ------------------------------------------------------------------
fLocator->setValues(fSchemaInfo->getCurrentSchemaURL(), 0,
((XSDElementNSImpl*) elem)->getLineNo(),
((XSDElementNSImpl*) elem)->getColumnNo());
InputSource* srcToFill = resolveSchemaLocation(schemaLocation,
XMLResourceIdentifier::SchemaImport, nameSpace);
// Nothing to do
if (!srcToFill) {
if (!grammarFound) {
addImportedNS(fURIStringPool->addOrFind(nameSpaceValue));
}
return;
}
Janitor<InputSource> janSrc(srcToFill);
const XMLCh* importURL = srcToFill->getSystemId();
unsigned int nameSpaceId = nameSpace ? fURIStringPool->addOrFind(nameSpace) : fEmptyNamespaceURI;
SchemaInfo* importSchemaInfo = fCachedSchemaInfoList->get(importURL, nameSpaceId);
if (!importSchemaInfo && fSchemaInfoList != fCachedSchemaInfoList)
importSchemaInfo = fSchemaInfoList->get(importURL, nameSpaceId);
if (importSchemaInfo) {
fSchemaInfo->addSchemaInfo(importSchemaInfo, SchemaInfo::IMPORT);
addImportedNS(importSchemaInfo->getTargetNSURI());
return;
}
if (grammarFound) {
if (!fScanner->getHandleMultipleImports())
return;
}
// ------------------------------------------------------------------
// Parse input source
// ------------------------------------------------------------------
if (!fParser)
fParser = new (fGrammarPoolMemoryManager) XSDDOMParser(0, fGrammarPoolMemoryManager, 0);
fParser->setValidationScheme(XercesDOMParser::Val_Never);
fParser->setDoNamespaces(true);
fParser->setUserEntityHandler(fEntityHandler);
fParser->setUserErrorReporter(fErrorReporter);
// Should just issue warning if the schema is not found
bool flag = srcToFill->getIssueFatalErrorIfNotFound();
srcToFill->setIssueFatalErrorIfNotFound(false);
fParser->parse(*srcToFill) ;
// Reset the InputSource
srcToFill->setIssueFatalErrorIfNotFound(flag);
if (fParser->getSawFatal() && fScanner->getExitOnFirstFatal())
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::SchemaScanFatalError);
// ------------------------------------------------------------------
// Get root element
// ------------------------------------------------------------------
DOMDocument* document = fParser->getDocument();
if (document) {
DOMElement* root = document->getDocumentElement();
if (!root) {
return;
}
const XMLCh* targetNSURIString = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
if (!XMLString::equals(targetNSURIString, nameSpaceValue)) {
reportSchemaError(root, XMLUni::fgXMLErrDomain, XMLErrs::ImportNamespaceDifference,
schemaLocation, targetNSURIString, nameSpaceValue);
}
else {
// --------------------------------------------------------
// Preprocess new schema
// --------------------------------------------------------
SchemaInfo* saveInfo = fSchemaInfo;
fSchemaGrammar->setScopeCount (fScopeCount);
fSchemaGrammar->setAnonTypeCount (fAnonXSTypeCount);
if (grammarFound) {
fSchemaGrammar = (SchemaGrammar*) aGrammar;
}
else {
fSchemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
}
fScopeCount = fSchemaGrammar->getScopeCount ();
fAnonXSTypeCount = fSchemaGrammar->getAnonTypeCount ();
XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) fSchemaGrammar->getGrammarDescription();
gramDesc->setContextType(XMLSchemaDescription::CONTEXT_IMPORT);
gramDesc->setLocationHints(importURL);
preprocessSchema(root, importURL, grammarFound);
fPreprocessedNodes->put((void*) elem, fSchemaInfo);
// --------------------------------------------------------
// Restore old schema information
// --------------------------------------------------------
restoreSchemaInfo(saveInfo, SchemaInfo::IMPORT);
}
}
}
void TraverseSchema::traverseImport(const DOMElement* const elem) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
SchemaInfo* importInfo = fPreprocessedNodes->get(elem);
if (importInfo) {
// --------------------------------------------------------
// Traverse new schema
// --------------------------------------------------------
SchemaInfo* saveInfo = fSchemaInfo;
restoreSchemaInfo(importInfo, SchemaInfo::IMPORT);
doTraverseSchema(importInfo->getRoot());
// --------------------------------------------------------
// Restore old schema information
// --------------------------------------------------------
restoreSchemaInfo(saveInfo, SchemaInfo::IMPORT);
}
}
/**
* Traverse redefine declaration
*
* <redefine>
* schemaLocation = uriReference
* {any attributes with non-schema namespace . . .}>
* Content: (annotation | (
* attributeGroup | complexType | group | simpleType))*
* </redefine>
*/
void TraverseSchema::preprocessRedefine(const DOMElement* const redefineElem) {
NamespaceScopeManager nsMgr(redefineElem, fSchemaInfo, this);
// -----------------------------------------------------------------------
// Check attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
redefineElem, GeneralAttributeCheck::E_Redefine, this, true
);
// First, we look through the children of redefineElem. Each one will
// correspond to an element of the redefined schema that we need to
// redefine. To do this, we rename the element of the redefined schema,
// and rework the base or ref tag of the kid we're working on to refer to
// the renamed group or derive the renamed type. Once we've done this, we
// actually go through the schema being redefined and convert it to a
// grammar. Only then do we run through redefineDecl's kids and put them
// in the grammar.
SchemaInfo* redefiningInfo = fSchemaInfo;
if (!openRedefinedSchema(redefineElem)) {
redefiningInfo->addFailedRedefine(redefineElem);
return;
}
if (!fRedefineComponents) {
fRedefineComponents = new (fMemoryManager) RefHash2KeysTableOf<XMLCh>(13, (bool) false, fMemoryManager);
}
SchemaInfo* redefinedInfo = fSchemaInfo;
renameRedefinedComponents(redefineElem, redefiningInfo, redefinedInfo);
// Now we have to preprocess our nicely-renamed schemas.
if (fPreprocessedNodes->containsKey(redefineElem)) {
fSchemaInfo = redefinedInfo;
preprocessChildren(fSchemaInfo->getRoot());
}
fSchemaInfo = redefiningInfo;
}
void TraverseSchema::traverseRedefine(const DOMElement* const redefineElem) {
NamespaceScopeManager nsMgr(redefineElem, fSchemaInfo, this);
SchemaInfo* saveInfo = fSchemaInfo;
SchemaInfo* redefinedInfo = fPreprocessedNodes->get(redefineElem);
if (redefinedInfo) {
// Now we have to march through our nicely-renamed schemas. When
// we do these traversals other <redefine>'s may perhaps be
// encountered; we leave recursion to sort this out.
fSchemaInfo = redefinedInfo;
processChildren(fSchemaInfo->getRoot());
fSchemaInfo = saveInfo;
// Now traverse our own <redefine>
processChildren(redefineElem);
}
}
/**
* Traverse the Choice, Sequence declaration
*
* <choice-sequence
* id = ID
* maxOccurs = (nonNegativeInteger | unbounded) : 1
* minOccurs = nonNegativeInteger : 1
* Content: (annotation?, (element | group | choice | sequence | any)*)
* </choice-sequence>
*/
ContentSpecNode*
TraverseSchema::traverseChoiceSequence(const DOMElement* const elem,
const int modelGroupType,
bool& hasChildren)
{
hasChildren = false;
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// -----------------------------------------------------------------------
// Check attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
elem, GeneralAttributeCheck::E_Sequence, this, false, fNonXSAttList
);
// -----------------------------------------------------------------------
// Process contents
// -----------------------------------------------------------------------
DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
Janitor<ContentSpecNode> left(0);
Janitor<ContentSpecNode> right(0);
bool hadContent = false;
Janitor<ContentSpecNode> contentSpecNode(0);
for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
hasChildren = true;
contentSpecNode.release();
bool seeParticle = false;
bool wasAny = false;
const XMLCh* childName = child->getLocalName();
if (XMLString::equals(childName, SchemaSymbols::fgELT_ELEMENT)) {
SchemaElementDecl* elemDecl = traverseElementDecl(child);
if (!elemDecl )
continue;
contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode
(
elemDecl
, fGrammarPoolMemoryManager
));
seeParticle = true;
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_GROUP)) {
XercesGroupInfo* grpInfo = traverseGroupDecl(child, false);
if (!grpInfo) {
continue;
}
ContentSpecNode* grpContentSpecNode = grpInfo->getContentSpec();
if (!grpContentSpecNode) {
continue;
}
if (grpContentSpecNode->hasAllContent()) {
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AllContentLimited);
continue;
}
contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode(*grpContentSpecNode));
seeParticle = true;
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) {
bool hasChild;
contentSpecNode.reset(traverseChoiceSequence(child,ContentSpecNode::Choice, hasChild));
seeParticle = true;
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) {
bool hasChild;
contentSpecNode.reset(traverseChoiceSequence(child,ContentSpecNode::Sequence, hasChild));
seeParticle = true;
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_ANY)) {
contentSpecNode.reset(traverseAny(child));
seeParticle = true;
wasAny = true;
}
else {
reportSchemaError(child, XMLUni::fgValidityDomain, XMLValid::GroupContentRestricted,
childName,
((ContentSpecNode::NodeTypes) modelGroupType) == ContentSpecNode::Choice?SchemaSymbols::fgELT_CHOICE:SchemaSymbols::fgELT_SEQUENCE);
}
if (seeParticle) {
checkMinMax(contentSpecNode.get(), child, Not_All_Context);
if (wasAny && contentSpecNode.get()->getMaxOccurs() == 0) {
contentSpecNode.reset(0);
}
}
if (contentSpecNode.get()) {
hadContent = true;
}
if (left.get() == 0) {
left.reset(contentSpecNode.release());
}
else if (right.get() == 0) {
right.reset(contentSpecNode.release());
}
else {
ContentSpecNode* newNode =
new (fGrammarPoolMemoryManager) ContentSpecNode
(
(ContentSpecNode::NodeTypes) modelGroupType
, left.get()
, right.get()
, true
, true
, fGrammarPoolMemoryManager
);
left.release();
right.release();
left.reset(newNode);
right.reset(contentSpecNode.release());
}
}
contentSpecNode.release();
if (hadContent)
{
ContentSpecNode* newNode =
new (fGrammarPoolMemoryManager) ContentSpecNode
(
((ContentSpecNode::NodeTypes) modelGroupType) == ContentSpecNode::Choice
? ContentSpecNode::ModelGroupChoice : ContentSpecNode::ModelGroupSequence
, left.get()
, right.get()
, true
, true
, fGrammarPoolMemoryManager
);
left.release();
left.reset(newNode);
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(left.get(), janAnnot.release());
}
right.release();
return left.release();
}
/**
* Traverse SimpleType declaration:
* <simpleType
* id = ID
* name = NCName>
* Content: (annotation? , ((list | restriction | union)))
* </simpleType>
*
* traverse <list>|<restriction>|<union>
*/
DatatypeValidator*
TraverseSchema::traverseSimpleTypeDecl(const DOMElement* const childElem,
const bool topLevel, int baseRefContext)
{
NamespaceScopeManager nsMgr(childElem, fSchemaInfo, this);
// ------------------------------------------------------------------
// Process contents
// ------------------------------------------------------------------
const XMLCh* name = getElementAttValue(childElem,SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
bool nameEmpty = (!name || !*name);
if (topLevel && nameEmpty) {
reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
SchemaSymbols::fgELT_SIMPLETYPE);
return 0;
}
else if(!topLevel && !nameEmpty) {
reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeDisallowedLocal,
SchemaSymbols::fgATT_NAME, childElem->getLocalName());
return 0;
}
if (nameEmpty) { // anonymous simpleType
name = genAnonTypeName(fgAnonSNamePrefix);
}
else if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) ) {
reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
SchemaSymbols::fgELT_SIMPLETYPE, name);
return 0;
}
fBuffer.set(fTargetNSURIString);
fBuffer.append(chComma);
fBuffer.append(name);
unsigned int fullTypeNameId = fStringPool->addOrFind(fBuffer.getRawBuffer());
const XMLCh* fullName = fStringPool->getValueForId(fullTypeNameId);
//check if we have already traversed the same simpleType decl
DatatypeValidator* dv = fDatatypeRegistry->getDatatypeValidator(fullName);
if (!dv) {
// -------------------------------------------------------------------
// Check attributes
// -------------------------------------------------------------------
unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_SimpleTypeGlobal
: GeneralAttributeCheck::E_SimpleTypeLocal;
fAttributeCheck.checkAttributes(
childElem, scope, this, topLevel, fNonXSAttList
);
// Circular constraint checking
if (fCurrentTypeNameStack->containsElement(fullTypeNameId)) {
reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, name);
return 0;
}
fCurrentTypeNameStack->addElement(fullTypeNameId);
// Get 'final' values
int finalSet = parseFinalSet(childElem, S_Final);
// annotation?,(list|restriction|union)
DOMElement* content= checkContent(
childElem, XUtil::getFirstChildElement(childElem), false);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(childElem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
if (content == 0) {
reportSchemaError(childElem, XMLUni::fgXMLErrDomain, XMLErrs::EmptySimpleTypeContent);
popCurrentTypeNameStack();
return 0;
}
const XMLCh* varietyName = content->getLocalName();
// Remark: some code will be repeated in list|restriction| union but it
// is cleaner that way
if (XMLString::equals(varietyName, SchemaSymbols::fgELT_LIST)) { //traverse List
if ((baseRefContext & SchemaSymbols::XSD_LIST) != 0) {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AtomicItemType);
popCurrentTypeNameStack();
return 0;
}
dv = traverseByList(childElem, content, name, fullName, finalSet, &janAnnot);
}
else if (XMLString::equals(varietyName, SchemaSymbols::fgELT_RESTRICTION)) { //traverse Restriction
dv = traverseByRestriction(childElem, content, name, fullName, finalSet, &janAnnot);
}
else if (XMLString::equals(varietyName, SchemaSymbols::fgELT_UNION)) { //traverse union
dv = traverseByUnion(childElem, content, name, fullName, finalSet, baseRefContext, &janAnnot);
}
else {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::FeatureUnsupported, varietyName);
popCurrentTypeNameStack();
}
if (dv) {
if (nameEmpty)
dv->setAnonymous();
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(dv, janAnnot.release());
}
}
return dv;
}
/**
* Traverse ComplexType Declaration - CR Implementation.
*
* <complexType
* abstract = boolean
* block = #all or (possibly empty) subset of {extension, restriction}
* final = #all or (possibly empty) subset of {extension, restriction}
* id = ID
* mixed = boolean : false
* name = NCName>
* Content: (annotation? , (simpleContent | complexContent |
* ( (group | all | choice | sequence)? ,
* ( (attribute | attributeGroup)* , anyAttribute?))))
* </complexType>
*/
int TraverseSchema::traverseComplexTypeDecl(const DOMElement* const elem,
const bool topLevel,
const XMLCh* const recursingTypeName) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// Get the attributes of the complexType
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
bool isAnonymous = false;
if (!name || !*name) {
if (topLevel) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameComplexType);
return -1;
}
if (recursingTypeName)
name = recursingTypeName;
else {
name = genAnonTypeName(fgAnonCNamePrefix);
isAnonymous = true;
}
}
if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)) ) {
//REVISIT - Should we return or continue and save type with wrong name?
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
SchemaSymbols::fgELT_COMPLEXTYPE, name);
return -1;
}
// ------------------------------------------------------------------
// Check if the type has already been registered
// ------------------------------------------------------------------
fBuffer.set(fTargetNSURIString);
fBuffer.append(chComma);
fBuffer.append(name);
int typeNameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer());
const XMLCh* fullName = fStringPool->getValueForId(typeNameIndex);
ComplexTypeInfo* typeInfo = 0;
if (topLevel || recursingTypeName) {
typeInfo = fComplexTypeRegistry->get(fullName);
if (typeInfo && !typeInfo->getPreprocessed()) {
return typeNameIndex;
}
}
// -----------------------------------------------------------------------
// Check Attributes
// -----------------------------------------------------------------------
bool preProcessFlag = (typeInfo) ? typeInfo->getPreprocessed() : false;
if (!preProcessFlag) {
fAttributeCheck.checkAttributes(
elem, (topLevel) ? GeneralAttributeCheck::E_ComplexTypeGlobal
: GeneralAttributeCheck::E_ComplexTypeLocal
, this, topLevel, fNonXSAttList
);
}
// -----------------------------------------------------------------------
// Create a new instance
// -----------------------------------------------------------------------
XMLSize_t previousCircularCheckIndex = fCircularCheckIndex;
unsigned int previousScope = fCurrentScope;
if (preProcessFlag) {
fCurrentScope = typeInfo->getScopeDefined();
typeInfo->setPreprocessed(false);
}
else {
// ------------------------------------------------------------------
// Register the type
// ------------------------------------------------------------------
typeInfo = new (fGrammarPoolMemoryManager) ComplexTypeInfo(fGrammarPoolMemoryManager);
if(isAnonymous) {
typeInfo->setAnonymous();
}
fCurrentScope = fScopeCount++;
fComplexTypeRegistry->put((void*) fullName, typeInfo);
typeInfo->setTypeName(fullName);
typeInfo->setScopeDefined(fCurrentScope);
if (fFullConstraintChecking) {
XSDLocator* aLocator = new (fGrammarPoolMemoryManager) XSDLocator();
aLocator->setValues(fStringPool->getValueForId(fStringPool->addOrFind(fSchemaInfo->getCurrentSchemaURL())),
0, ((XSDElementNSImpl*) elem)->getLineNo(),
((XSDElementNSImpl*) elem)->getColumnNo());
typeInfo->setLocator(aLocator);
}
}
fCurrentTypeNameStack->addElement(typeNameIndex);
ComplexTypeInfo* saveTypeInfo = fCurrentComplexType;
fCurrentComplexType = typeInfo;
// ------------------------------------------------------------------
// First, handle any ANNOTATION declaration and get next child
// ------------------------------------------------------------------
DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true, !preProcessFlag);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
// ------------------------------------------------------------------
// Process the content of the complex type declaration
// ------------------------------------------------------------------
try {
const XMLCh* mixedVal = getElementAttValue(elem,SchemaSymbols::fgATT_MIXED, DatatypeValidator::Boolean);
bool isMixed = false;
if ((mixedVal && *mixedVal)
&& (XMLString::equals(SchemaSymbols::fgATTVAL_TRUE, mixedVal)
|| XMLString::equals(fgValueOne, mixedVal))) {
isMixed = true;
}
if (child == 0) {
// EMPTY complexType with complexContent
processComplexContent(elem, name, child, typeInfo, 0, isMixed);
}
else {
const XMLCh* childName = child->getLocalName();
if (XMLString::equals(childName, SchemaSymbols::fgELT_SIMPLECONTENT)) {
// SIMPLE CONTENT element
traverseSimpleContentDecl(name, fullName, child, typeInfo, &janAnnot);
if (XUtil::getNextSiblingElement(child) != 0) {
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingSimpleContent);
}
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_COMPLEXCONTENT)) {
// COMPLEX CONTENT element
traverseComplexContentDecl(name, child, typeInfo, isMixed, &janAnnot);
if (XUtil::getNextSiblingElement(child) != 0) {
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::InvalidChildFollowingConplexContent);
}
}
else if (fCurrentGroupInfo) {
typeInfo->setPreprocessed(true);
}
else {
// We must have ....
// GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes
// Note that it's possible that only attributes are specified.
processComplexContent(elem, name, child, typeInfo, 0, isMixed);
}
}
}
catch(const TraverseSchema::ExceptionCodes aCode) {
if (aCode == TraverseSchema::InvalidComplexTypeInfo)
defaultComplexTypeInfo(typeInfo);
else if (aCode == TraverseSchema::RecursingElement)
typeInfo->setPreprocessed();
}
// ------------------------------------------------------------------
// Finish the setup of the typeInfo
// ------------------------------------------------------------------
if (!preProcessFlag) {
const XMLCh* abstractAttVal = getElementAttValue(elem, SchemaSymbols::fgATT_ABSTRACT, DatatypeValidator::Boolean);
int blockSet = parseBlockSet(elem, C_Block);
int finalSet = parseFinalSet(elem, EC_Final);
typeInfo->setBlockSet(blockSet);
typeInfo->setFinalSet(finalSet);
if ((abstractAttVal && *abstractAttVal)
&& (XMLString::equals(abstractAttVal, SchemaSymbols::fgATTVAL_TRUE)
|| XMLString::equals(abstractAttVal, fgValueOne))) {
typeInfo->setAbstract(true);
}
else {
typeInfo->setAbstract(false);
}
}
// Store Annotation
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(typeInfo, janAnnot.release());
// ------------------------------------------------------------------
// Before exiting, restore the scope, mainly for nested anonymous types
// ------------------------------------------------------------------
popCurrentTypeNameStack();
fCircularCheckIndex = previousCircularCheckIndex;
fCurrentScope = previousScope;
fCurrentComplexType = saveTypeInfo;
return typeNameIndex;
}
/**
* Traverse Group Declaration.
*
* <group
* id = ID
* maxOccurs = string
* minOccurs = nonNegativeInteger
* name = NCName
* ref = QName>
* Content: (annotation? , (all | choice | sequence)?)
* <group/>
*
*/
XercesGroupInfo*
TraverseSchema::traverseGroupDecl(const DOMElement* const elem,
const bool topLevel) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName);
bool nameEmpty = (!name || !*name);
bool refEmpty = (!ref || !*ref);
if (nameEmpty && topLevel) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
SchemaSymbols::fgELT_GROUP);
return 0;
}
if (nameEmpty && refEmpty) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefGroup);
return 0;
}
// ------------------------------------------------------------------
// Check attributes
// ------------------------------------------------------------------
unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_GroupGlobal
: GeneralAttributeCheck::E_GroupRef;
fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList);
// ------------------------------------------------------------------
// Handle "ref="
// ------------------------------------------------------------------
if (!topLevel) {
if (refEmpty) {
return 0;
}
return processGroupRef(elem, ref);
}
// name must be a valid NCName
if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
SchemaSymbols::fgELT_GROUP, name);
return 0;
}
fBuffer.set(fTargetNSURIString);
fBuffer.append(chComma);
fBuffer.append(name);
unsigned int nameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer());
const XMLCh* fullName = fStringPool->getValueForId(nameIndex);
XercesGroupInfo* groupInfo = fGroupRegistry->get(fullName);
if (groupInfo) {
return groupInfo;
}
// ------------------------------------------------------------------
// Check for annotations
// ------------------------------------------------------------------
DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
// ------------------------------------------------------------------
// Process contents of global groups
// ------------------------------------------------------------------
unsigned int saveScope = fCurrentScope;
Janitor<ContentSpecNode> specNode(0);
XercesGroupInfo* saveGroupInfo = fCurrentGroupInfo;
Janitor<XercesGroupInfo> newGroupInfoJan(new (fGrammarPoolMemoryManager) XercesGroupInfo(
fStringPool->addOrFind(name), fTargetNSURI, fGrammarPoolMemoryManager));
fCurrentGroupStack->addElement(nameIndex);
XercesGroupInfo* const newGroupInfo = newGroupInfoJan.get();
fCurrentGroupInfo = newGroupInfo;
fCurrentScope = fScopeCount++;
fCurrentGroupInfo->setScope(fCurrentScope);
if (content == 0) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::GroupContentError, name);
}
else {
if (content->getAttributeNode(SchemaSymbols::fgATT_MINOCCURS) != 0
|| content->getAttributeNode(SchemaSymbols::fgATT_MAXOCCURS) != 0) {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::MinMaxOnGroupChild);
}
bool illegalChild = false;
const XMLCh* childName = content->getLocalName();
bool hasChild;
if (XMLString::equals(childName, SchemaSymbols::fgELT_SEQUENCE)) {
specNode.reset(traverseChoiceSequence(content, ContentSpecNode::Sequence, hasChild));
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_CHOICE)) {
specNode.reset(traverseChoiceSequence(content, ContentSpecNode::Choice, hasChild));
}
else if (XMLString::equals(childName, SchemaSymbols::fgELT_ALL)) {
specNode.reset(traverseAll(content, hasChild));
}
else {
illegalChild = true;
}
if (illegalChild || XUtil::getNextSiblingElement(content) != 0) {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::GroupContentError, name);
}
// copy local elements to complex type if it exists
if (fCurrentComplexType)
processElements(elem, fCurrentGroupInfo, fCurrentComplexType);
}
// ------------------------------------------------------------------
// Set groupInfo and pop group name from stack
// ------------------------------------------------------------------
XMLSize_t stackSize = fCurrentGroupStack->size();
if (stackSize != 0) {
fCurrentGroupStack->removeElementAt(stackSize - 1);
}
fCurrentGroupInfo->setContentSpec(specNode.release());
fGroupRegistry->put((void*) fullName, fCurrentGroupInfo);
newGroupInfoJan.release();
fCurrentGroupInfo = saveGroupInfo;
fCurrentScope = saveScope;
// Store Annotation
if (!janAnnot.isDataNull()) {
fSchemaGrammar->putAnnotation(newGroupInfo, janAnnot.release());
}
if (fFullConstraintChecking) {
XSDLocator* aLocator = new (fGrammarPoolMemoryManager) XSDLocator();
newGroupInfo->setLocator(aLocator);
aLocator->setValues(fStringPool->getValueForId(fStringPool->addOrFind(fSchemaInfo->getCurrentSchemaURL())),
0, ((XSDElementNSImpl*) elem)->getLineNo(),
((XSDElementNSImpl*) elem)->getColumnNo());
if (fRedefineComponents && fRedefineComponents->get(SchemaSymbols::fgELT_GROUP, nameIndex))
{
fBuffer.set(fullName);
fBuffer.append(SchemaSymbols::fgRedefIdentifier);
unsigned int rdfNameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer());
if (fCurrentGroupStack->containsElement(rdfNameIndex))
{
reportSchemaError(aLocator, XMLUni::fgXMLErrDomain, XMLErrs::NoCircularDefinition, name);
}
else
{
XercesGroupInfo* baseGroup = fGroupRegistry->get(fBuffer.getRawBuffer());
if (baseGroup)
{
newGroupInfo->setBaseGroup(baseGroup);
}
else
{
fBuffer.set(name);
fBuffer.append(SchemaSymbols::fgRedefIdentifier);
SchemaInfo* saveInfo = fSchemaInfo;
DOMElement* groupElem = fSchemaInfo->getTopLevelComponent(SchemaInfo::C_Group,
SchemaSymbols::fgELT_GROUP, fBuffer.getRawBuffer(), &fSchemaInfo);
if (groupElem != 0) {
baseGroup = traverseGroupDecl(groupElem);
newGroupInfo->setBaseGroup(baseGroup);
fSchemaInfo = saveInfo;
}
else
{
reportSchemaError(aLocator, XMLUni::fgXMLErrDomain, XMLErrs::DeclarationNotFound,
SchemaSymbols::fgELT_GROUP, fTargetNSURIString, fBuffer.getRawBuffer());
}
}
}
}
}
return newGroupInfo;
}
/**
* Traverse attributeGroup Declaration.
*
* <attributeGroup
* id = ID
* name = NCName
* ref = QName>
* Content: (annotation? , (attribute|attributeGroup)*, anyAttribute?)
* <attributeGroup/>
*
*/
XercesAttGroupInfo*
TraverseSchema::traverseAttributeGroupDecl(const DOMElement* const elem,
ComplexTypeInfo* const typeInfo,
const bool topLevel) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName);
bool nameEmpty = (!name || !*name) ? true : false;
bool refEmpty = (!ref || !*ref) ? true : false;
if (nameEmpty && topLevel) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
SchemaSymbols::fgELT_ATTRIBUTEGROUP);
return 0;
}
if (nameEmpty && refEmpty) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttGroup);
return 0;
}
// ------------------------------------------------------------------
// Check attributes
// ------------------------------------------------------------------
unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_AttributeGroupGlobal
: GeneralAttributeCheck::E_AttributeGroupRef;
fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList);
// ------------------------------------------------------------------
// Handle "ref="
// ------------------------------------------------------------------
XercesAttGroupInfo* attGroupInfo;
Janitor<XercesAttGroupInfo> janAttGroupInfo(0);
if (!topLevel) {
if (refEmpty) {
return 0;
}
attGroupInfo = processAttributeGroupRef(elem, ref, typeInfo);
}
else
{
// name must be a valid NCName
if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
SchemaSymbols::fgELT_ATTRIBUTEGROUP, name);
return 0;
}
// Check for annotations
DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
// Process contents of global attributeGroups
XercesAttGroupInfo* saveAttGroupInfo = fCurrentAttGroupInfo;
janAttGroupInfo.reset(new (fGrammarPoolMemoryManager) XercesAttGroupInfo(
fStringPool->addOrFind(name), fTargetNSURI, fGrammarPoolMemoryManager));
fDeclStack->addElement(elem);
fCurrentAttGroupInfo = janAttGroupInfo.get();
for (; content !=0; content = XUtil::getNextSiblingElement(content)) {
if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ATTRIBUTE)) {
traverseAttributeDecl(content, typeInfo);
}
else if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ATTRIBUTEGROUP)) {
traverseAttributeGroupDecl(content, typeInfo);
}
else {
break;
}
}
if (content != 0) {
if (XMLString::equals(content->getLocalName(), SchemaSymbols::fgELT_ANYATTRIBUTE)) {
SchemaAttDef* anyAtt = traverseAnyAttribute(content);
if (anyAtt) {
fCurrentAttGroupInfo->addAnyAttDef(anyAtt);
}
if (XUtil::getNextSiblingElement(content) != 0) {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AttGroupContentError, name);
}
}
else {
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AttGroupContentError, name);
}
}
// Pop declaration
fDeclStack->removeElementAt(fDeclStack->size() - 1);
fAttGroupRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), janAttGroupInfo.get());
// Restore old attGroupInfo
attGroupInfo = janAttGroupInfo.release();
fCurrentAttGroupInfo = saveAttGroupInfo;
// Check Attribute Derivation Restriction OK
fBuffer.set(fTargetNSURIString);
fBuffer.append(chComma);
fBuffer.append(name);
unsigned int nameIndex = fStringPool->addOrFind(fBuffer.getRawBuffer());
if (fRedefineComponents && fRedefineComponents->get(SchemaSymbols::fgELT_ATTRIBUTEGROUP, nameIndex)) {
fBuffer.set(name);
fBuffer.append(SchemaSymbols::fgRedefIdentifier);
XercesAttGroupInfo* baseAttGroupInfo = fAttGroupRegistry->get(fBuffer.getRawBuffer());
if (baseAttGroupInfo)
checkAttDerivationOK(elem, baseAttGroupInfo, attGroupInfo);
}
// Store annotation
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(attGroupInfo, janAnnot.release());
}
// calculate complete wildcard if necessary
if (attGroupInfo)
{
XMLSize_t anyAttCount = attGroupInfo->anyAttributeCount();
if (anyAttCount && !attGroupInfo->getCompleteWildCard())
{
SchemaAttDef* attGroupWildCard = new (fGrammarPoolMemoryManager)
SchemaAttDef(attGroupInfo->anyAttributeAt(0));
for (XMLSize_t k= 1; k < anyAttCount; k++)
attWildCardIntersection(attGroupWildCard, attGroupInfo->anyAttributeAt(k));
attGroupInfo->setCompleteWildCard(attGroupWildCard);
}
}
return attGroupInfo;
}
inline XercesAttGroupInfo*
TraverseSchema::traverseAttributeGroupDeclNS(const DOMElement* const elem,
const XMLCh* const uriStr,
const XMLCh* const name) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// ------------------------------------------------------------------
// Get grammar information
// ------------------------------------------------------------------
Grammar* aGrammar = fGrammarResolver->getGrammar(uriStr);
if (!aGrammar || aGrammar->getGrammarType() != Grammar::SchemaGrammarType) {
reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::GrammarNotFound, uriStr);
return 0;
}
XercesAttGroupInfo* attGroupInfo = ((SchemaGrammar*)aGrammar)->getAttGroupInfoRegistry()->get(name);
return attGroupInfo;
}
/**
* Traverse Any declaration
*
* <any
* id = ID
* maxOccurs = (nonNegativeInteger | unbounded) : 1
* minOccurs = nonNegativeInteger : 1
* namespace = ((##any | ##other) | List of (anyURI |
* (##targetNamespace | ##local)) ) : ##any
* processContents = (lax | skip | strict) : strict
* {any attributes with non-schema namespace . . .}>
* Content: (annotation?)
* </any>
*/
ContentSpecNode*
TraverseSchema::traverseAny(const DOMElement* const elem) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// -----------------------------------------------------------------------
// Check Attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
elem, GeneralAttributeCheck::E_Any, this, false, fNonXSAttList
);
// ------------------------------------------------------------------
// First, handle any ANNOTATION declaration
// ------------------------------------------------------------------
if (checkContent(elem, XUtil::getFirstChildElement(elem), true) != 0)
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::OnlyAnnotationExpected);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
// ------------------------------------------------------------------
// Get attributes
// ------------------------------------------------------------------
const XMLCh* const processContents = getElementAttValue(elem, SchemaSymbols::fgATT_PROCESSCONTENTS);
const XMLCh* const nameSpace = getElementAttValue(elem, SchemaSymbols::fgATT_NAMESPACE);
// ------------------------------------------------------------------
// Set default node type based on 'processContents' value
// ------------------------------------------------------------------
ContentSpecNode::NodeTypes anyType = ContentSpecNode::Any;
ContentSpecNode::NodeTypes anyLocalType = ContentSpecNode::Any_NS;
ContentSpecNode::NodeTypes anyOtherType = ContentSpecNode::Any_Other;
if ((processContents && *processContents)
&& !XMLString::equals(processContents, SchemaSymbols::fgATTVAL_STRICT)) {
if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_LAX)) {
anyType = ContentSpecNode::Any_Lax;
anyOtherType = ContentSpecNode::Any_Other_Lax;
anyLocalType = ContentSpecNode::Any_NS_Lax;
}
else if (XMLString::equals(processContents, SchemaSymbols::fgATTVAL_SKIP)) {
anyType = ContentSpecNode::Any_Skip;
anyOtherType = ContentSpecNode::Any_Other_Skip;
anyLocalType = ContentSpecNode::Any_NS_Skip;
}
}
// ------------------------------------------------------------------
// Process 'namespace' attribute
// ------------------------------------------------------------------
ContentSpecNode* retSpecNode = 0;
if ((!nameSpace || !*nameSpace)
|| XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDANY)) {
retSpecNode = new (fGrammarPoolMemoryManager) ContentSpecNode
(
new (fGrammarPoolMemoryManager) QName
(
XMLUni::fgZeroLenString
, XMLUni::fgZeroLenString
, fEmptyNamespaceURI
, fGrammarPoolMemoryManager
)
, false
, fGrammarPoolMemoryManager
);
retSpecNode->setType(anyType);
}
else if (XMLString::equals(nameSpace, SchemaSymbols::fgATTVAL_TWOPOUNDOTHER)) {
retSpecNode = new (fGrammarPoolMemoryManager) ContentSpecNode
(
new (fGrammarPoolMemoryManager) QName
(
XMLUni::fgZeroLenString
, XMLUni::fgZeroLenString
, fTargetNSURI, fGrammarPoolMemoryManager
)
, false
, fGrammarPoolMemoryManager
);
retSpecNode->setType(anyOtherType);
}
else {
XMLStringTokenizer nameSpaceTokens(nameSpace, fMemoryManager);
ValueVectorOf<unsigned int> uriList(8, fGrammarPoolMemoryManager);
Janitor<ContentSpecNode> firstNode(0);
Janitor<ContentSpecNode> secondNode(0);
DatatypeValidator* anyURIDV = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYURI);
while (nameSpaceTokens.hasMoreTokens()) {
const XMLCh* tokenElem = nameSpaceTokens.nextToken();
int uriIndex = fEmptyNamespaceURI;
if (!XMLString::equals(tokenElem,SchemaSymbols::fgATTVAL_TWOPOUNDLOCAL)) { // not ##local
if (XMLString::equals(tokenElem,SchemaSymbols::fgATTVAL_TWOPOUNDTRAGETNAMESPACE)) {
uriIndex = fTargetNSURI;
}
else {
try {
anyURIDV->validate(tokenElem
, fSchemaInfo->getValidationContext()
, fMemoryManager);
}
catch(const XMLException& excep) {
reportSchemaError(elem, excep);
}
uriIndex = fURIStringPool->addOrFind(tokenElem);
}
}
if (uriList.containsElement(uriIndex)) {
continue;
}
uriList.addElement(uriIndex);
firstNode.release();
firstNode.reset( new (fGrammarPoolMemoryManager) ContentSpecNode
(
new (fGrammarPoolMemoryManager) QName
(
XMLUni::fgZeroLenString
, XMLUni::fgZeroLenString
, uriIndex, fGrammarPoolMemoryManager
)
, false
, fGrammarPoolMemoryManager
));
firstNode.get()->setType(anyLocalType);
if (secondNode.get() == 0) {
secondNode.reset(firstNode.release());
}
else {
ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode
(
ContentSpecNode::Any_NS_Choice
, secondNode.get()
, firstNode.get()
, true
, true
, fGrammarPoolMemoryManager
);
secondNode.release();
secondNode.reset(newNode);
firstNode.release();
}
}
firstNode.release();
retSpecNode = secondNode.release();
}
// Store annotation
if (retSpecNode && !janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(retSpecNode, janAnnot.release());
return retSpecNode;
}
/**
* Traverse all
*
* <all
* id = ID
* maxOccurs = 1 : 1
* minOccurs = (0 | 1) : 1
* {any attributes with non-schema namespace . . .}>
* Content: (annotation?, element*)
* </all>
*/
ContentSpecNode*
TraverseSchema::traverseAll(const DOMElement* const elem, bool& hasChildren) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
hasChildren = false;
// -----------------------------------------------------------------------
// Check attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
elem, GeneralAttributeCheck::E_All, this, false, fNonXSAttList
);
// -----------------------------------------------------------------------
// Process contents
// -----------------------------------------------------------------------
DOMElement* child = checkContent(elem, XUtil::getFirstChildElement(elem), true);
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
if (child == 0) {
return 0;
}
Janitor<ContentSpecNode> left(0);
Janitor<ContentSpecNode> right(0);
Janitor<ContentSpecNode> contentSpecNode(0);
bool hadContent = false;
for (; child != 0; child = XUtil::getNextSiblingElement(child)) {
hasChildren = true;
contentSpecNode.release();
const XMLCh* childName = child->getLocalName();
if (XMLString::equals(childName, SchemaSymbols::fgELT_ELEMENT)) {
SchemaElementDecl* elemDecl = traverseElementDecl(child);
if (!elemDecl)
continue;
contentSpecNode.reset(new (fGrammarPoolMemoryManager) ContentSpecNode
(
elemDecl
, fGrammarPoolMemoryManager
));
checkMinMax(contentSpecNode.get(), child, All_Element);
}
else {
reportSchemaError(child, XMLUni::fgXMLErrDomain, XMLErrs::AllContentError, childName);
continue;
}
hadContent = true;
if (!left.get()) {
left.reset(contentSpecNode.release());
}
else if (!right.get()) {
right.reset(contentSpecNode.release());
}
else {
ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode
(
ContentSpecNode::All
, left.get()
, right.get()
, true
, true
, fGrammarPoolMemoryManager
);
left.release();
left.reset(newNode);
right.release();
right.reset(contentSpecNode.release());
}
}
contentSpecNode.release();
if (hadContent) {
ContentSpecNode* newNode = new (fGrammarPoolMemoryManager) ContentSpecNode
(
ContentSpecNode::All
, left.get()
, right.get()
, true
, true
, fGrammarPoolMemoryManager
);
left.release();
left.reset(newNode);
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(left.get(), janAnnot.release());
}
right.release();
return left.release();
}
/**
* Traverses Schema attribute declaration.
*
* <attribute
* fixed = string
* default = string
* form = qualified | unqualified
* id = ID
* name = NCName
* ref = QName
* type = QName
* use = optional | prohibited | required : optional
>
* Content: (annotation? , simpleType?)
* <attribute/>
*
* @param elem: the declaration of the attribute under consideration
*
* @param typeInfo: Contains the complex type info of the element to which
* the attribute declaration is attached.
*
*/
void TraverseSchema::traverseAttributeDecl(const DOMElement* const elem,
ComplexTypeInfo* const typeInfo,
const bool topLevel) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
const XMLCh* ref = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName);
bool nameEmpty = (!name || !*name);
bool refEmpty = (!ref || !*ref);
if (nameEmpty && refEmpty) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefAttribute);
return;
}
if (topLevel && nameEmpty) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::TopLevelNoNameAttribute);
return;
}
// ------------------------------------------------------------------
// Check attributes
// ------------------------------------------------------------------
unsigned short scope = (topLevel)
? GeneralAttributeCheck::E_AttributeGlobal
: (refEmpty) ? GeneralAttributeCheck::E_AttributeLocal
: GeneralAttributeCheck::E_AttributeRef;
fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList);
const XMLCh* defaultVal = getElementAttValue(elem, SchemaSymbols::fgATT_DEFAULT);
const XMLCh* fixedVal = getElementAttValue(elem, SchemaSymbols::fgATT_FIXED);
const XMLCh* useVal = getElementAttValue(elem, SchemaSymbols::fgATT_USE);
const XMLCh* attForm = getElementAttValue(elem, SchemaSymbols::fgATT_FORM);
const XMLCh* dvType = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE, DatatypeValidator::QName);
DOMElement* simpleType = checkContent(elem, XUtil::getFirstChildElement(elem), true);
Janitor<XSAnnotation> janAnnot(fAnnotation);
bool badContent = false;
while (simpleType != 0) {
const XMLCh* contentName = simpleType->getLocalName();
if (XMLString::equals(SchemaSymbols::fgELT_SIMPLETYPE, contentName)) {
if (XUtil::getNextSiblingElement(simpleType) != 0) {
badContent = true;
}
break;
}
badContent = true;
simpleType = XUtil::getNextSiblingElement(simpleType);
}
if (badContent) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttributeContent,
(name) ? name : ref);
}
if (defaultVal) {
if (fixedVal) {
fixedVal = 0;
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeDefaultFixedValue,
(name) ? name : ref);
}
if ((useVal && *useVal)
&& !XMLString::equals(useVal, SchemaSymbols::fgATTVAL_OPTIONAL)) {
useVal = 0;
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NotOptionalDefaultAttValue,
(name) ? name : ref);
}
}
// processing ref
if (!refEmpty && !topLevel) {
// Check ref representation OK - 3.2.3::3.2
if (attForm || dvType || (simpleType != 0)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeRefContentError,
(name) ? name : ref);
}
processAttributeDeclRef(elem, typeInfo, ref, useVal, defaultVal, fixedVal);
return;
}
if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
janAnnot.reset(fAnnotation);
}
// processing 'name'
if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))
|| XMLString::equals(name, XMLUni::fgXMLNSString)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ATTRIBUTE, name);
return;
}
// Check for duplicate declaration
const XMLCh* qualified = SchemaSymbols::fgATTVAL_QUALIFIED;
int uriIndex = fEmptyNamespaceURI;
if ((fTargetNSURIString && *fTargetNSURIString)
&& (topLevel || XMLString::equals(attForm, qualified)
|| ((fSchemaInfo->getElemAttrDefaultQualified() & Attr_Def_Qualified)
&& (!attForm || !*attForm)))) {
uriIndex = fTargetNSURI;
}
// make sure that attribute namespace is not xsi uri
if (XMLString::equals(fTargetNSURIString, SchemaSymbols::fgURI_XSI)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidAttTNS, name);
return;
}
if (typeInfo && typeInfo->getAttDef(name, uriIndex) != 0) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name);
return;
}
else if (fCurrentAttGroupInfo && fCurrentAttGroupInfo->containsAttribute(name, uriIndex)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateAttribute, name);
return;
}
DatatypeValidator* dv = 0;
XMLAttDef::AttTypes attType = XMLAttDef::Simple;
SchemaInfo* saveInfo = fSchemaInfo;
if (simpleType != 0) {
if (dvType && *dvType) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttributeWithTypeAndSimpleType, name);
}
dv = traverseSimpleTypeDecl(simpleType, false);
}
else if (!dvType || !*dvType) {
dv = fDatatypeRegistry->getDatatypeValidator(SchemaSymbols::fgDT_ANYSIMPLETYPE);
}
else {
checkEnumerationRequiredNotation(elem, name, dvType);
const XMLCh* localPart = getLocalPart(dvType);
const XMLCh* prefix = getPrefix(dvType);
const XMLCh* typeURI = resolvePrefixToURI(elem, prefix);
DatatypeValidator* dvBack = 0;
if (XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
dv = fDatatypeRegistry->getDatatypeValidator(localPart);
dvBack = dv;
}
else { //isn't of the schema for schemas namespace...
dv = getAttrDatatypeValidatorNS(elem, localPart, typeURI);
dvBack = dv;
while(dv != 0 && !XMLString::equals(dv->getTypeUri(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
dv = dv->getBaseValidator();
}
if(dv)
localPart = dv->getTypeLocalName();
}
if(dv) {
if (XMLString::equals(localPart,XMLUni::fgIDString)) {
attType = XMLAttDef::ID;
}
else if (XMLString::equals(localPart,XMLUni::fgIDRefString)) {
attType = XMLAttDef::IDRef;
}
else if (XMLString::equals(localPart,XMLUni::fgIDRefsString)) {
attType = XMLAttDef::IDRefs;
}
else if (XMLString::equals(localPart,XMLUni::fgEntityString)) {
attType = XMLAttDef::Entity;
}
else if (XMLString::equals(localPart,XMLUni::fgEntitiesString)) {
attType = XMLAttDef::Entities;
}
else if (XMLString::equals(localPart,XMLUni::fgNmTokenString)) {
attType = XMLAttDef::NmToken;
}
else if (XMLString::equals(localPart,XMLUni::fgNmTokensString)) {
attType = XMLAttDef::NmTokens;
}
else if (XMLString::equals(localPart,XMLUni::fgNotationString)) {
attType = XMLAttDef::Notation;
}
else {
attType = XMLAttDef::Simple;
}
}
else
attType = XMLAttDef::Simple;
dv = dvBack;
if (!dv) {
reportSchemaError
(
elem
, XMLUni::fgXMLErrDomain
, XMLErrs::AttributeSimpleTypeNotFound
, typeURI
, localPart
, name
);
}
}
// restore schema information, if necessary
fSchemaInfo = saveInfo;
bool required = false;
bool prohibited = false;
if (useVal && *useVal) {
if (XMLString::equals(useVal, SchemaSymbols::fgATTVAL_REQUIRED)) {
required = true;
}
else if (XMLString::equals(useVal, SchemaSymbols::fgATTVAL_PROHIBITED)) {
prohibited = true;
}
}
// validate fixed/default values
const XMLCh* valueToCheck = defaultVal ? defaultVal : fixedVal;
bool ofTypeID = (dv && dv->getType() == DatatypeValidator::ID);
if (attType == XMLAttDef::Simple && dv && valueToCheck) {
short wsFacet = dv->getWSFacet();
if((wsFacet == DatatypeValidator::REPLACE && !XMLString::isWSReplaced(valueToCheck)) ||
(wsFacet == DatatypeValidator::COLLAPSE && !XMLString::isWSCollapsed(valueToCheck)))
{
XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager);
ArrayJanitor<XMLCh> tempURIName(normalizedValue, fMemoryManager);
if(wsFacet == DatatypeValidator::REPLACE)
XMLString::replaceWS(normalizedValue, fMemoryManager);
else if(wsFacet == DatatypeValidator::COLLAPSE)
XMLString::collapseWS(normalizedValue, fMemoryManager);
valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue));
}
try {
dv->validate(valueToCheck
, fSchemaInfo->getValidationContext()
, fMemoryManager);
}
catch (const XMLException& excep) {
reportSchemaError(elem, excep);
}
catch(const OutOfMemoryException&)
{
throw;
}
catch(...) {
reportSchemaError(elem, XMLUni::fgValidityDomain, XMLValid::DatatypeValidationFailure, valueToCheck);
}
}
else if((attType == XMLAttDef::NmTokens || attType==XMLAttDef::IDRefs || attType==XMLAttDef::Entities) &&
valueToCheck && !XMLString::isWSCollapsed(valueToCheck))
{
XMLCh* normalizedValue=XMLString::replicate(valueToCheck, fMemoryManager);
ArrayJanitor<XMLCh> tempURIName(normalizedValue, fMemoryManager);
XMLString::collapseWS(normalizedValue, fMemoryManager);
valueToCheck=fStringPool->getValueForId(fStringPool->addOrFind(normalizedValue));
}
if (ofTypeID && valueToCheck) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect3, name);
}
// check for multiple attributes with type derived from ID
if (!topLevel && ofTypeID) {
if (fCurrentAttGroupInfo) {
if (fCurrentAttGroupInfo->containsTypeWithId()) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttGrpPropCorrect3, name);
return;
}
fCurrentAttGroupInfo->setTypeWithId(true);
}
else {
if (typeInfo->containsAttWithTypeId()) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::AttDeclPropCorrect5, name);
return;
}
typeInfo->setAttWithTypeId(true);
}
}
// create SchemaAttDef
SchemaAttDef* attDef = new (fGrammarPoolMemoryManager) SchemaAttDef
(
XMLUni::fgZeroLenString
, name
, uriIndex
, attType
, XMLAttDef::Implied
, fGrammarPoolMemoryManager
);
attDef->setDatatypeValidator(dv);
if (prohibited) {
attDef->setDefaultType(XMLAttDef::Prohibited);
}
else if (required) {
if (fixedVal) {
attDef->setDefaultType(XMLAttDef::Required_And_Fixed);
}
else {
attDef->setDefaultType(XMLAttDef::Required);
}
}
else {
if (fixedVal) {
attDef->setDefaultType(XMLAttDef::Fixed);
}
else if (defaultVal) {
attDef->setDefaultType(XMLAttDef::Default);
}
}
if (valueToCheck) {
attDef->setValue(valueToCheck);
}
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(attDef, janAnnot.release());
if (topLevel)
{
fAttributeDeclRegistry->put((void*) fStringPool->getValueForId(fStringPool->addOrFind(name)), attDef);
attDef->setPSVIScope(PSVIDefs::SCP_GLOBAL);
}
else
{
if (typeInfo)
{
typeInfo->addAttDef(attDef);
if (!fCurrentAttGroupInfo)
attDef->setPSVIScope(PSVIDefs::SCP_LOCAL);
}
if (fCurrentAttGroupInfo) {
fCurrentAttGroupInfo->addAttDef(attDef, (typeInfo != 0));
}
}
}
/**
* Traverses Schema element declaration.
*
* <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
*/
SchemaElementDecl*
TraverseSchema::traverseElementDecl(const DOMElement* const elem,
const bool topLevel)
{
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// if local element and ref attribute exists
if (!topLevel)
{
const XMLCh* refName = getElementAttValue(elem, SchemaSymbols::fgATT_REF, DatatypeValidator::QName);
if (refName)
return processElementDeclRef(elem, refName);
}
// check for empty name
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
if (!name || !*name)
{
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameRefElement);
return 0;
}
// make sure that name is a valid NCName
if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name)))
{
reportSchemaError(elem, XMLUni::fgXMLErrDomain,
XMLErrs::InvalidDeclarationName, SchemaSymbols::fgELT_ELEMENT, name);
return 0;
}
// if element already exists, just return --- revisit, it should not happen
if (topLevel)
{
SchemaElementDecl* retDecl = (SchemaElementDecl*) fSchemaGrammar->getElemDecl(fTargetNSURI, name, 0, Grammar::TOP_LEVEL_SCOPE);
if (retDecl)
return retDecl;
}
// Check attributes
unsigned short scope = (topLevel) ? GeneralAttributeCheck::E_ElementGlobal
: GeneralAttributeCheck::E_ElementLocal;
fAttributeCheck.checkAttributes(elem, scope, this, topLevel, fNonXSAttList);
// check annotation
const DOMElement* content = checkContent(elem, XUtil::getFirstChildElement(elem), true);
// Put annotations on all elements for the situation where there is a group of
// elements and not all have annotations.
//if (fScanner->getGenerateSyntheticAnnotations() && !fAnnotation && fNonXSAttList->size())
if (!fAnnotation && fScanner->getGenerateSyntheticAnnotations())
{
fAnnotation = generateSyntheticAnnotation(elem, fNonXSAttList);
}
Janitor<XSAnnotation> janAnnot(fAnnotation);
// Create element decl
bool isDuplicate = false;
const XMLCh* valueConstraint = 0;
SchemaElementDecl* elemDecl =
createSchemaElementDecl(elem, name, isDuplicate, valueConstraint, topLevel);
if (!isDuplicate) {
fSchemaGrammar->putElemDecl(elemDecl);
if (valueConstraint)
elemDecl->setDefaultValue(valueConstraint);
if (!janAnnot.isDataNull())
fSchemaGrammar->putAnnotation(elemDecl, janAnnot.release());
if (fCurrentComplexType &&
elemDecl->getEnclosingScope() == fCurrentComplexType->getScopeDefined()) {
fCurrentComplexType->addElement(elemDecl);
elemDecl->setPSVIScope(PSVIDefs::SCP_LOCAL);
}
if (fCurrentGroupInfo &&
elemDecl->getEnclosingScope() == fCurrentGroupInfo->getScope()) {
fCurrentGroupInfo->addElement(elemDecl);
elemDecl->setPSVIScope(PSVIDefs::SCP_ABSENT);
}
}
else {
if (fAnnotation) {
XSAnnotation* xsAnnot = fSchemaGrammar->getAnnotation(elemDecl);
if (!xsAnnot) {
fSchemaGrammar->putAnnotation(elemDecl, janAnnot.release());
}
else {
xsAnnot->setNext(janAnnot.release());
}
}
}
// Process children
bool anonymousType = false;
ComplexTypeInfo* typeInfo = 0;
DatatypeValidator* validator = 0;
if (content != 0)
{
const XMLCh* contentName = content->getLocalName();
if (XMLString::equals(contentName, SchemaSymbols::fgELT_COMPLEXTYPE))
{
const XMLCh* temp = content->getAttribute(SchemaSymbols::fgATT_NAME);
if (temp && *temp)
{
// REVISIT - we are bypassing the complex type declaration.
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AnonComplexTypeWithName, name);
}
else
{
typeInfo = checkForComplexTypeInfo(content);
if (typeInfo)
{
validator = typeInfo->getDatatypeValidator();
if (!isDuplicate) {
//Recursing element
if (typeInfo->getPreprocessed()) {
const XMLCh* typeInfoName = typeInfo->getTypeName();
fSchemaInfo->addRecursingType(content, typeInfoName + XMLString::indexOf(typeInfoName, chComma) + 1);
}
}
}
}
anonymousType = true;
content = XUtil::getNextSiblingElement(content);
}
else if (XMLString::equals(contentName, SchemaSymbols::fgELT_SIMPLETYPE))
{
const XMLCh* temp = content->getAttribute(SchemaSymbols::fgATT_NAME);
if (temp && *temp)
// REVISIT - we are bypassing the simple type declaration.
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::AnonSimpleTypeWithName, name);
else
validator = checkForSimpleTypeValidator(content);
anonymousType = true;
content = XUtil::getNextSiblingElement(content);
}
// Check for identity constraints
if (content != 0)
{
content = checkIdentityConstraintContent(content);
if (content != 0)
reportSchemaError(content, XMLUni::fgXMLErrDomain, XMLErrs::InvalidElementContent);
}
}
// Handle 'type' attribute
const XMLCh* typeStr = getElementAttValue(elem, SchemaSymbols::fgATT_TYPE, DatatypeValidator::QName);
if (typeStr)
{
if (anonymousType)
{
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::ElementWithTypeAndAnonType, name);
}
else if (*typeStr)
{
const XMLCh* typeLocalPart = getLocalPart(typeStr);
const XMLCh* typePrefix = getPrefix(typeStr);
const XMLCh* typeURI = resolvePrefixToURI(elem, typePrefix);
if (!XMLString::equals(typeURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)
|| !XMLString::equals(typeLocalPart, SchemaSymbols::fgATTVAL_ANYTYPE))
{
checkEnumerationRequiredNotation(elem, name, typeStr);
bool noErrorFound = true;
const XMLCh* anotherSchemaURI = checkTypeFromAnotherSchema(elem, typeStr);
// get complex type info
typeInfo = getElementComplexTypeInfo(elem, typeStr, anotherSchemaURI);
// get simple type validtor - if not a complex type
if (typeInfo)
validator = typeInfo->getDatatypeValidator();
else
validator = getElementTypeValidator(elem, typeStr, noErrorFound, anotherSchemaURI);
}
}
}
// check for duplicate elements with different types.
if (isDuplicate)
{
DatatypeValidator* eltDV = elemDecl->getDatatypeValidator();
ComplexTypeInfo* eltTypeInfo = elemDecl->getComplexTypeInfo();
if ( (eltTypeInfo != typeInfo) || (eltDV != validator)) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::DuplicateElementDeclaration, name);
}
}
// Set element declararion type information
else
{
elemDecl->setDatatypeValidator(validator);
elemDecl->setComplexTypeInfo(typeInfo);
if (validator)
elemDecl->setModelType(SchemaElementDecl::Simple);
else if (typeInfo)
elemDecl->setModelType((SchemaElementDecl::ModelTypes)typeInfo->getContentType());
if (topLevel) {
// Handle the substitutionGroup
const XMLCh* subsGroupName = getElementAttValue(elem, SchemaSymbols::fgATT_SUBSTITUTIONGROUP, DatatypeValidator::QName);
if (subsGroupName && *subsGroupName)
processSubstitutionGroup(elem, elemDecl, typeInfo, validator, subsGroupName);
}
// process identity constraints
DOMElement* ic = XUtil::getFirstChildElementNS(
elem, fgIdentityConstraints, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, 3);
if (ic)
processElemDeclIC(ic, elemDecl);
}
if (!typeInfo && !validator)
{
if (!isDuplicate)
{
elemDecl->setModelType(SchemaElementDecl::Any);
elemDecl->setAttWildCard(
new (fGrammarPoolMemoryManager) SchemaAttDef(
XMLUni::fgZeroLenString, XMLUni::fgZeroLenString,
fEmptyNamespaceURI, XMLAttDef::Any_Any,
XMLAttDef::ProcessContents_Lax, fGrammarPoolMemoryManager
)
);
}
}
else if (valueConstraint)
{
if (!checkElemDeclValueConstraint(elem, elemDecl, valueConstraint, typeInfo, validator)
&& !isDuplicate)
{
int miscFlags = elemDecl->getMiscFlags();
miscFlags &= ~ SchemaSymbols::XSD_FIXED;
elemDecl->setDefaultValue(0);
elemDecl->setMiscFlags(miscFlags);
}
}
return elemDecl;
}
/**
* Traverses Schema notation declaration.
*
* <notation
* id = ID
* name = NCName
* public = token
* system = anyURI
* {any attributes with non-schema namespace . . .}>
* Content: (annotation?)
* </notation>
*
* @param elem: the declaration of the element under consideration
*/
const XMLCh* TraverseSchema::traverseNotationDecl(const DOMElement* const elem) {
NamespaceScopeManager nsMgr(elem, fSchemaInfo, this);
// -----------------------------------------------------------------------
// Check attributes
// -----------------------------------------------------------------------
fAttributeCheck.checkAttributes(
elem, GeneralAttributeCheck::E_Notation, this, true, fNonXSAttList
);
// -----------------------------------------------------------------------
// Process notation attributes/elements
// -----------------------------------------------------------------------
const XMLCh* name = getElementAttValue(elem, SchemaSymbols::fgATT_NAME, DatatypeValidator::NCName);
bool nameEmpty = (!name || !*name) ? true : false;
if (nameEmpty) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::NoNameGlobalElement,
SchemaSymbols::fgELT_NOTATION);
return 0;
}
if (!XMLChar1_0::isValidNCName(name, XMLString::stringLen(name))) {
reportSchemaError(elem, XMLUni::fgXMLErrDomain, XMLErrs::InvalidDeclarationName,
SchemaSymbols::fgELT_NOTATION, name);
return 0;
}
if (fNotationRegistry->containsKey(name, fTargetNSURI)) {
return name;