bool SequenceType::ItemType::matchesSchemaElement(const Node::Ptr &toBeTested, const DynamicContext* context) const { // retrieve the type of the element name assert(m_pName!=NULL); const XMLCh* elementNS=m_NameURI; const XMLCh* elementName=m_pName->getName(); SchemaElementDecl *elemDecl=context->getDocumentCache()->getElementDecl(elementNS, elementName); assert(elemDecl != NULL); // 1. The name of the candidate node matches the specified ElementName or matches the name of an element in a // substitution group headed by an element named ElementName. ATQNameOrDerived::Ptr name = toBeTested->dmNodeName(context); if(name.isNull()) return false; const XMLCh *node_uri = ((const ATQNameOrDerived*)name.get())->getURI(); const XMLCh *node_name = ((const ATQNameOrDerived*)name.get())->getName(); if(!(XPath2Utils::equals(elementName, node_name)) || !(XPath2Utils::equals(elementNS, node_uri))) { // the node doesn't match the ElementName; check if it is in its substitution group SchemaElementDecl* thisElemDecl=context->getDocumentCache()->getElementDecl(node_uri, node_name); if(thisElemDecl==NULL) // the node to be tested has no type info return false; SchemaElementDecl* rootElemDecl=thisElemDecl->getSubstitutionGroupElem(); bool foundIt=false; while (rootElemDecl) { if (XPath2Utils::equals(rootElemDecl->getBaseName(), elementName) && XPath2Utils::equals(context->getDocumentCache()->getSchemaUri(rootElemDecl->getURI()), elementNS)) { foundIt = true; break; } rootElemDecl = rootElemDecl->getSubstitutionGroupElem(); } if(!foundIt) return false; } // 2. derives-from(AT, ET) is true, where AT is the type of the candidate node and ET is the type declared for // element ElementName in the in-scope element declarations. ComplexTypeInfo* pTypeInfo=elemDecl->getComplexTypeInfo(); if(pTypeInfo && !toBeTested->hasInstanceOfType(pTypeInfo->getTypeUri(), pTypeInfo->getTypeLocalName(), context)) return false; // 3. Either the nilled property of the candidate node is false, or the element declaration for ElementName in // the in-scope element declarations is nillable. if(toBeTested->dmNilled(context).get()->isTrue() && !(elemDecl->getMiscFlags() & SchemaSymbols::XSD_NILLABLE)) return false; return true; }
bool SequenceType::ItemType::matchesNameType(const Item::Ptr &toBeTested, const DynamicContext* context) const { // Check name constraint if(m_pName) { if(toBeTested->isNode()) { ATQNameOrDerived::Ptr name = ((const Node*)(const Item*)toBeTested)->dmNodeName(context); if(name.isNull()) return false; // Match node name if(!(XPath2Utils::equals(m_pName->getName(), ((const ATQNameOrDerived*)name.get())->getName()))) return false; // Match node uri if(!(XPath2Utils::equals(m_NameURI, ((const ATQNameOrDerived*)name.get())->getURI()))) return false; } else return false; } //A named atomic type matches a value if the dynamic type of the //value is the same as the named atomic type or is derived from the //named atomic type by restriction. For example, the ItemType //xs:decimal matches the value 12.34 (a decimal literal); it also //matches a value whose dynamic type is shoesize, if shoesize is an //atomic type derived from xs:decimal. if(m_pType) { if(toBeTested->isAtomicValue()) { return ((AnyAtomicType*)toBeTested.get())->isInstanceOfType(m_TypeURI, m_pType->getName(), context); } else if (toBeTested->isNode()) { return ((Node*)toBeTested.get())->hasInstanceOfType(m_TypeURI, m_pType->getName(), context); } return false; } return true; }
bool SequenceType::ItemType::matches(const Node::Ptr &toBeTested, DynamicContext* context) const { switch(m_nTestType) { case TEST_ELEMENT: { if(toBeTested->dmNodeKind() != Node::element_string) return false; if(!matchesNameType(toBeTested, context)) return false; // if the element has xsi:nil="true", m_bAllowNil MUST be true if(toBeTested->dmNilled(context)->isTrue() && !m_bAllowNil) return false; return true; } case TEST_ATTRIBUTE: { if(toBeTested->dmNodeKind() != Node::attribute_string) return false; if(!matchesNameType(toBeTested, context)) return false; return true; } case TEST_SCHEMA_ELEMENT: { if(toBeTested->dmNodeKind() != Node::element_string) return false; return matchesSchemaElement(toBeTested, context); } case TEST_SCHEMA_ATTRIBUTE: { if(toBeTested->dmNodeKind() != Node::attribute_string) return false; // retrieve the type of the attribute name assert(m_pName!=NULL); const XMLCh* attributeNS=m_NameURI; const XMLCh* attributeName=m_pName->getName(); SchemaAttDef* attrDecl=context->getDocumentCache()->getAttributeDecl(attributeNS, attributeName); assert(attrDecl != NULL); // 1. The name of the candidate node matches the specified AttributeName ATQNameOrDerived::Ptr name = toBeTested->dmNodeName(context); if(name.isNull()) return false; const XMLCh *node_uri = ((const ATQNameOrDerived*)name.get())->getURI(); const XMLCh *node_name = ((const ATQNameOrDerived*)name.get())->getName(); if(!(XPath2Utils::equals(attributeName, node_name)) || !(XPath2Utils::equals(attributeNS, node_uri))) return false; // 2. derives-from(AT, ET) is true, where AT is the type of the candidate node and ET is the type declared // for attribute AttributeName in the in-scope attribute declarations. DatatypeValidator* pDV=attrDecl->getDatatypeValidator(); if(pDV && !toBeTested->hasInstanceOfType(pDV->getTypeUri(), pDV->getTypeLocalName(), context)) return false; return true; } case TEST_PI: { if(toBeTested->dmNodeKind() != Node::processing_instruction_string) return false; if(!matchesNameType(toBeTested, context)) return false; return true; } case TEST_COMMENT: { return (toBeTested->dmNodeKind() == Node::comment_string); } case TEST_TEXT: { return (toBeTested->dmNodeKind() == Node::text_string); } case TEST_SCHEMA_DOCUMENT: case TEST_DOCUMENT: { if(toBeTested->dmNodeKind() != Node::document_string) return false; if(m_pName == NULL && m_pType == NULL) return true; // if we have a constraint on name/type, they apply to the document element Result children = toBeTested->dmChildren(context, 0); Node::Ptr docElement; while((docElement = children->next(context)).notNull() && docElement->dmNodeKind() != Node::element_string) {} if(docElement.isNull()) return false; if(m_nTestType == TEST_DOCUMENT) return matchesNameType(docElement, context); else return matchesSchemaElement(docElement, context); } case TEST_NODE: case TEST_ANYTHING: { return true; } case TEST_ATOMIC_TYPE: case TEST_FUNCTION: { return false; } } return true; }