Sequence FunctionLocalname::createSequence(DynamicContext* context, int flags) const { XPath2MemoryManager* memMgr = context->getMemoryManager(); Node::Ptr ctxNode; if(getNumArgs() == 1) { Sequence arg=getParamNumber(1,context)->toSequence(context); if(arg.isEmpty()) return Sequence(context->getItemFactory()->createString(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context), memMgr); ctxNode=arg.first(); } else { const Item::Ptr item = context->getContextItem(); if(item==NULLRCP) XQThrow(FunctionException, X("FunctionLocalName::createSequence"),X("Undefined context item in fn:local-name [err:XPDY0002]")); if(!item->isNode()) XQThrow(FunctionException, X("FunctionLocalName::createSequence"),X("The context item is not a node [err:XPTY0004]")); ctxNode=item; } ATQNameOrDerived::Ptr name = ctxNode->dmNodeName(context); if(name.notNull()) return Sequence(context->getItemFactory()->createString(((const ATQNameOrDerived*)name.get())->getName(), context), memMgr); return Sequence(context->getItemFactory()->createString(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context), memMgr); }
void Node::typeToBuffer(DynamicContext *context, XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer &buffer) const { buffer.append(dmNodeKind()); buffer.append('('); if(dmNodeKind() == element_string || dmNodeKind() == attribute_string) { ATQNameOrDerived::Ptr qname = dmNodeName(context); if(qname->getURI()) { buffer.append('{'); buffer.append(qname->getURI()); buffer.append('}'); } buffer.append(qname->getName()); buffer.append(','); buffer.append(' '); if(getTypeURI()) { buffer.append('{'); buffer.append(getTypeURI()); buffer.append('}'); } buffer.append(getTypeName()); } buffer.append(')'); }
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; }
PendingUpdateList URename::createUpdateList(DynamicContext *context) const { Node::Ptr node = (Node*)target_->createResult(context)->next(context).get(); if(node->dmNodeKind() != Node::element_string && node->dmNodeKind() != Node::attribute_string && node->dmNodeKind() != Node::processing_instruction_string) XQThrow(XPath2TypeMatchException,X("URename::createUpdateList"), X("It is a type error for the target expression of a rename expression not to be a single element, " "attribute or processing instruction [err:XUTY0012]")); ATQNameOrDerived::Ptr qname = (ATQNameOrDerived*)name_->createResult(context)->next(context).get(); // 3. The following checks are performed for error conditions: // a. If $target is an element node, the "namespaces" property of $target must not include any namespace binding that conflicts // with the implied namespace binding of $QName [err:XUDY0023]. if(node->dmNodeKind() == Node::element_string) { if(!UInsertAsLast::checkNamespaceBinding(qname, node, context, this)) { XMLBuffer buf; buf.append(X("Implied namespace binding for the rename expression (\"")); buf.append(qname->getPrefix()); buf.append(X("\" -> \"")); buf.append(qname->getURI()); buf.append(X("\") conflicts with those already existing on the target element [err:XUDY0023]")); XQThrow(DynamicErrorException, X("URename::createUpdateList"), buf.getRawBuffer()); } } // b. If $target is an attribute node that has a parent, the "namespaces" property of parent($target) must not include any // namespace binding that conflicts with the implied namespace binding of $QName [err:XUDY0023]. else if(node->dmNodeKind() == Node::attribute_string) { Node::Ptr parentNode = node->dmParent(context); if(parentNode.notNull() && !UInsertAsLast::checkNamespaceBinding(qname, parentNode, context, this)) { XMLBuffer buf; buf.append(X("Implied namespace binding for the rename expression (\"")); buf.append(qname->getPrefix()); buf.append(X("\" -> \"")); buf.append(qname->getURI()); buf.append(X("\") conflicts with those already existing on the parent element of the target attribute [err:XUDY0023]")); XQThrow(DynamicErrorException, X("URename::createUpdateList"), buf.getRawBuffer()); } } // c. If $target is processing instruction node, $QName must not include a non-empty namespace prefix. [err:XUDY0025]. else if(node->dmNodeKind() == Node::processing_instruction_string && !XPath2Utils::equals(qname->getPrefix(), XMLUni::fgZeroLenString)) XQThrow(XPath2TypeMatchException,X("URename::createUpdateList"), X("The target of a rename expression is a processing instruction node, and the new name " "expression returned a QName with a non-empty namespace prefix [err:XUDY0025]")); return PendingUpdate(PendingUpdate::RENAME, node, qname, this); }
PendingUpdateList UInsertAsLast::createUpdateList(DynamicContext *context) const { Node::Ptr node = (Node*)target_->createResult(context)->next(context).get(); if(node->dmNodeKind() != Node::element_string && node->dmNodeKind() != Node::document_string) XQThrow(XPath2TypeMatchException,X("UInsertAsLast::createUpdateList"), X("It is a type error for the target expression of an insert as last expression not to be a single element " "or document [err:XUTY0005]")); Sequence alist(context->getMemoryManager()); Sequence clist(context->getMemoryManager()); Result value = source_->createResult(context); Item::Ptr item; while((item = value->next(context)).notNull()) { if(((Node*)item.get())->dmNodeKind() == Node::attribute_string) { if(!clist.isEmpty()) XQThrow(ASTException,X("UInsertAsLast::createUpdateList"), X("Attribute nodes must occur before other nodes in the source expression for an insert as last expression [err:XUTY0004]")); // b. No attribute node in $alist may have a QName whose implied namespace binding conflicts with a namespace // binding in the "namespaces" property of $target [err:XUDY0023]. ATQNameOrDerived::Ptr qname = ((Node*)item.get())->dmNodeName(context); if(qname->getURI() != 0 && *(qname->getURI()) != 0) { ATAnyURIOrDerived::Ptr uri = FunctionNamespaceURIForPrefix::uriForPrefix(qname->getPrefix(), node, context, this); if(uri.notNull() && !XPath2Utils::equals(uri->asString(context), qname->getURI())) { XMLBuffer buf; buf.append(X("Implied namespace binding for the insert as last expression (\"")); buf.append(qname->getPrefix()); buf.append(X("\" -> \"")); buf.append(qname->getURI()); buf.append(X("\") conflicts with those already existing on the parent element of the target attribute [err:XUDY0023]")); XQThrow3(DynamicErrorException, X("UInsertInto::createUpdateList"), buf.getRawBuffer(), this); } } alist.addItem(item); } else clist.addItem(item); } PendingUpdateList result; if(!alist.isEmpty()) { // 3. If $alist is not empty and into is specified, the following checks are performed: // a. $target must be an element node [err:XUTY0022]. if(node->dmNodeKind() == Node::document_string) XQThrow(XPath2TypeMatchException,X("UInsertInto::createUpdateList"), X("It is a type error if an insert expression specifies the insertion of an attribute node into a document node [err:XUTY0022]")); result.addUpdate(PendingUpdate(PendingUpdate::INSERT_ATTRIBUTES, node, alist, this)); } if(!clist.isEmpty()) { result.addUpdate(PendingUpdate(PendingUpdate::INSERT_INTO_AS_LAST, node, clist, this)); } return result; }
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; }