#include "../../config/pathan_config.h" /* * Copyright (c) 2003, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include "NodeImpl.hpp" #include #include #include #include #include "../../exceptions/XPath2TypeCastException.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const XMLCh NodeImpl::ls_string[] = { XERCES_CPP_NAMESPACE_QUALIFIER chLatin_L, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_S, XERCES_CPP_NAMESPACE_QUALIFIER chNull }; NodeImpl::NodeImpl(const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node, XPath2MemoryManager* memMgr) : Node(memMgr), fSerializer(0), fNode(node), uniqueTypeName(0) { assert(fNode!=0); } bool NodeImpl::isNode() const { return true; } bool NodeImpl::isAtomicValue() const { return false; } void NodeImpl::release() const { //TODO needs to check for ownership before releasing! getMemoryManager()->deallocate((void*)this); } const XMLCh* NodeImpl::asString(const DynamicContext* context) const { if(!fSerializer) { XERCES_CPP_NAMESPACE_QUALIFIER DOMImplementation *impl = XERCES_CPP_NAMESPACE_QUALIFIER DOMImplementationRegistry::getDOMImplementation(ls_string); ((NodeImpl*)this)->fSerializer = ((XERCES_CPP_NAMESPACE_QUALIFIER DOMImplementationLS*)impl)->createDOMWriter(context->getMemoryManager()); } return fSerializer->writeToString(*fNode); } /** check if the underlying type of this node is instance of a certain type */ bool NodeImpl::hasInstanceOfType(const XMLCh* typeURI, const XMLCh* typeName, const DynamicContext* context) const { return context->isTypeOrDerivedFromType(getTypeURI(), getTypeName(), typeURI, typeName); } /* Accessor functions */ Sequence NodeImpl::dmBaseURI(const DynamicContext* context) const { switch (fNode->getNodeType()) { case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE : case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::DOCUMENT_NODE : case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::PROCESSING_INSTRUCTION_NODE : { const XMLCh *tmp = fNode->getBaseURI(); if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(tmp)) { const ATAnyURIOrDerived *tempURI = DatatypeFactory::STR2AT::createAnyURI(context->getMemoryManager(), tmp, context); return Sequence(tempURI, context->getMemoryManager()); } } default : return Sequence(context->getMemoryManager()); } } // The dm:node-kind accessor returns a string value representing the // node's kind: either "document", "element", "attribute", "text", // "namespace", "processing-instruction", or "comment". const XMLCh* NodeImpl::dmNodeKind(void) const { switch(fNode->getNodeType()) { case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::DOCUMENT_NODE: return document_string; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE: return element_string; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ATTRIBUTE_NODE: return attribute_string; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TEXT_NODE: return text_string; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::PROCESSING_INSTRUCTION_NODE: return processing_instruction_string; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::COMMENT_NODE: return comment_string; case XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathNamespace::XPATH_NAMESPACE_NODE: return namespace_string; } DSLthrow(ItemException, X("NodeImpl::dmNodeKind"), X("Unknown node type.")); } Sequence NodeImpl::dmNodeName(const DynamicContext* context) const { switch(fNode->getNodeType()) { case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE: return Sequence(DatatypeFactory::STR2AT::createQName(context->getMemoryManager(), fNode->getNamespaceURI(), fNode->getLocalName(), context), context->getMemoryManager()); case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ATTRIBUTE_NODE: return Sequence(DatatypeFactory::STR2AT::createQName(context->getMemoryManager(), fNode->getNamespaceURI(), fNode->getLocalName(), context), context->getMemoryManager()); case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::PROCESSING_INSTRUCTION_NODE: return Sequence(DatatypeFactory::STR2AT::createQName(context->getMemoryManager(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString,fNode->getNodeName(), context), context->getMemoryManager()); case XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathNamespace::XPATH_NAMESPACE_NODE: { const XMLCh* prefix = fNode->getPrefix(); if(prefix == 0) { return Sequence(context->getMemoryManager()); } return Sequence(DatatypeFactory::STR2AT::createQName(context->getMemoryManager(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, prefix, context), context->getMemoryManager()); } case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::DOCUMENT_NODE: case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TEXT_NODE: case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::COMMENT_NODE: return Sequence(context->getMemoryManager()); } return Sequence(context->getMemoryManager()); } void NodeImpl::addStringValueToBuffer(const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node, XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer& buffer) const { short nodeType=node->getNodeType(); if(nodeType==XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TEXT_NODE || nodeType==XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::CDATA_SECTION_NODE) { buffer.append(node->getNodeValue()); } else { for(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* child=node->getFirstChild();child!=NULL;child=child->getNextSibling()) addStringValueToBuffer(child,buffer); } } //The dm:string-value accessor returns the node's string //representation. For some kinds of nodes, this is part of the node; //for other kinds of nodes, it is computed from the dm:string-value of //its descendant nodes. const XMLCh* NodeImpl::dmStringValue(const DynamicContext* context) const { switch(fNode->getNodeType()) { case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::DOCUMENT_NODE: { // Returns the concatenation of the string-values of all its text node descendants in document order XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer str(1023, context->getMemoryManager()); addStringValueToBuffer(fNode,str); return context->getMemoryManager()->getPooledString(str.getRawBuffer()); } break; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE: { XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer str(1023, context->getMemoryManager()); if(hasTypeInfo()) { const XMLCh *typeName = getTypeName(); const XMLCh *typeUri = getTypeURI(); //Returns the string value calculated as follows: // - If the element has a type of xdt:untypedAny, a complex type with complex content, or a complex type with mixed content, // returns the concatenation of the string-values of all its text node descendants in document order. // It returns "" if the element has no text node descendants. // - If the element has a complex type with empty content, returns "". if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgATTVAL_ANYTYPE) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA) || context->getDocumentCache()->getComplexTypeInfo(typeUri, typeName)!=NULL) addStringValueToBuffer(fNode,str); else { // - If the element has a simple type or a complex type with simple content: // - If the element type is xs:string, or a type derived from xs:string, returns that string. if(context->getDocumentCache()->isTypeOrDerivedFromType(typeUri,typeName,XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_STRING)) str.set(fNode->getTextContent()); // - If the element type is xs:anyURI, returns the characters of the URI. else if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_ANYURI) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) str.set(fNode->getTextContent()); // - If the element type is xs:QName returns the value calculated as follows: // - If the value has no namespace URI and the in-scope namespaces map the default namespace to any // namespace URI, then an error is raised ("default namespace is defined"). // - If the value has a namespace URI, then there must be at least one prefix mapped to that URI in // the in-scope namespaces. If there is no such prefix, an error is raised ("no prefix defined for namespace"). // If there is more than one such prefix, the one that is chosen is implementation dependent. // - If no error occurs, returns a string with the lexical form of a xs:QName using the prefix chosen // as described above, and the local name of the value. else if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_QNAME) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { // REVISIT: the rules assume that a QName has been expanded upon loading, but we don't do that... str.set(fNode->getTextContent()); } // - If the element type is xs:dateTime, xs:date, or xs:time, returns the original lexical representation of // the typed value recovered as follows: if an explicit timezone was present, the normalized value is adjusted // using the explicit timezone; if an explicit timezone was not present, the Z is dropped from the normalized value. // The normalized value and the explicit timezone, if present, are converted separately to xs:string and concatenated // to yield the string value. else if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA) && (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_DATETIME) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_DATE) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_TIME))) { const Item* item = DatatypeFactory::STR2AT::createDerivedFromAtomicType(context->getMemoryManager(), typeUri, typeName, fNode->getTextContent(), context); str.set(item->asString(context)); } // - In all other cases, returns the concatenation of the string-values of all its text node descendants in document order. else addStringValueToBuffer(fNode,str); } } else addStringValueToBuffer(fNode,str); return context->getMemoryManager()->getPooledString(str.getRawBuffer()); } break; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ATTRIBUTE_NODE: if(hasTypeInfo()) { const XMLCh *typeName = getTypeName(); const XMLCh *typeUri = getTypeURI(); // Returns the value calculated as follows: // - If the attribute type is xdt:untypedAtomic, xs:string, or a type derived from xs:string, returns that string. if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, ATUntypedAtomic::fgDT_UNTYPEDATOMIC) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, FunctionConstructor::XMLChXPath2DatatypesURI) || context->getDocumentCache()->isTypeOrDerivedFromType(typeUri,typeName,XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_STRING)) return fNode->getTextContent(); // - If the attribute type is xs:anyURI, returns the characters of the URI. else if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_ANYURI) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) return fNode->getTextContent(); // - If the attribute type is xs:QName returns the value calculated as follows: // - If the value has no namespace URI, then an error is raised ("default namespace is defined") if the in-scope // namespaces map the default namespace to any namespace URI. // - If the value has a namespace URI, then there must be at least one prefix mapped to that URI in the in-scope // namespaces. If there is no such prefix, an error is raised ("no prefix defined for namespace"). // If there is more than one such prefix, the one that is chosen is implementation dependent. // - If no error occurs, returns a string with the lexical form of a xs:QName using the prefix chosen as described // above, and the local name of the value. else if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_QNAME) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { // REVISIT: the rules assume that a QName has been expanded upon loading, but we don't do that... return fNode->getTextContent(); } // - If the attribute type is xs:dateTime, xs:date, or xs:time, returns the original lexical representation recovered as follows: // - if an explicit timezone was present, the normalized value is adjusted using the explicit timezone; // - if an explicit timezone was not present, the Z is dropped from the normalized value. // The normalized value and the explicit timezone, if present, are converted separately to xs:string and concatenated to yield the string value. else if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA) && (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_DATETIME) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_DATE) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_TIME))) { const Item* item = DatatypeFactory::STR2AT::createDerivedFromAtomicType(context->getMemoryManager(), typeUri, typeName, fNode->getTextContent(), context); return item->asString(context); } // REVISIT: this fallback case is not in the spec, but otherwise, how could we compute the string-value of an attribute // of type "double" ???? else return fNode->getTextContent(); } else return fNode->getTextContent(); break; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::PROCESSING_INSTRUCTION_NODE: case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::COMMENT_NODE: case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TEXT_NODE: case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::CDATA_SECTION_NODE: // Returns the value of the content property. return fNode->getTextContent(); break; case XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathNamespace::XPATH_NAMESPACE_NODE: // Returns the value of the uri property. return fNode->getTextContent(); break; } return XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString; } Sequence NodeImpl::getListTypeTypedValue(XERCES_CPP_NAMESPACE_QUALIFIER DatatypeValidator *dtv, const DynamicContext* context) const { const XMLCh *stringVal = dmStringValue(context); //the actual type we want XERCES_CPP_NAMESPACE_QUALIFIER DatatypeValidator* theItemTypeDTV = ((XERCES_CPP_NAMESPACE_QUALIFIER ListDatatypeValidator*)dtv)->getItemTypeDTV(); XERCES_CPP_NAMESPACE_QUALIFIER BaseRefVectorOf* tokenVector = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::tokenizeString(stringVal); const XMLCh* itemTypeDTVName = theItemTypeDTV->getTypeLocalName(); const XMLCh* itemTypeDTVUri = theItemTypeDTV->getTypeUri(); Sequence s(tokenVector->size(), context->getMemoryManager()); for ( unsigned int j = 0; j < tokenVector->size(); j++ ) s.addItem(DatatypeFactory::STR2AT::createDerivedFromAtomicType(context->getMemoryManager(), itemTypeDTVUri, itemTypeDTVName, tokenVector->elementAt(j), context)); return s; } Sequence NodeImpl::dmTypedValue(const DynamicContext* context) const { /* cerr<<"NodeImpl::dmTypedValue getTypeName(): "<getNodeName())<getNamespaceURI())<getNodeType()) { case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ATTRIBUTE_NODE: { if(hasTypeInfo()) { const XMLCh *typeName = getTypeName(); const XMLCh *typeUri = getTypeURI(); const Item *item = 0; //cerr<<"NodeImpl::dmTypedValue getTypeName(): "<getMemoryManager(), dmStringValue(context), context); return Sequence(item, context->getMemoryManager()); } else { XERCES_CPP_NAMESPACE_QUALIFIER DatatypeValidator *dtv = context->getDocumentCache()->getDatatypeValidator(typeUri, typeName); //dtv may be null when we update DOMTypeInfo!! if(!dtv) { assert(false); XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer msg(1023, context->getMemoryManager()); msg.set(X("The datatype {")); msg.append(typeUri); msg.append(X("}")); msg.append(typeName); msg.append(X(" is unknown")); DSLthrow(XPath2TypeCastException,X("NodeImpl::dmTypedValue"), msg.getRawBuffer()); } if(dtv->getType() == XERCES_CPP_NAMESPACE_QUALIFIER DatatypeValidator::List) { return getListTypeTypedValue(dtv, context); } else { item = DatatypeFactory::STR2AT::createDerivedFromAtomicType(context->getMemoryManager(), typeUri, typeName, dmStringValue(context), context); return Sequence(item, context->getMemoryManager()); } } } else { /* XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer b; b.set(X("Attempt to get typed value from an attribute with no type information. Type name is ")); b.append(getTypeName()); b.append(X(",type uri is ")); b.append(getTypeURI()); b.append(X(",node name is ")); b.append(fNode->getNodeName()); b.append(X(", node uri is ")); b.append(fNode->getNamespaceURI()); throw PathanException(XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathException::TYPE_ERR, b.getRawBuffer() ); */ //return untypedatomic for now const Item *item = DatatypeFactory::STR2AT::createUntypedAtomic(context->getMemoryManager(), dmStringValue(context), context); return Sequence(item, context->getMemoryManager()); } } break; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE: { if(hasTypeInfo()) { const XMLCh *typeName = getTypeName(); const XMLCh *typeUri = getTypeURI(); if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeName, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgATTVAL_ANYTYPE) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeUri, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { const Item *item = DatatypeFactory::STR2AT::createUntypedAtomic(context->getMemoryManager(), dmStringValue(context), context); return Sequence(item, context->getMemoryManager()); } XERCES_CPP_NAMESPACE_QUALIFIER DatatypeValidator *dtv = context->getDocumentCache()->getDatatypeValidator(typeUri, typeName); if(dtv) { if(dtv->getType() == XERCES_CPP_NAMESPACE_QUALIFIER DatatypeValidator::List) { return getListTypeTypedValue(dtv, context); } else { const Item *item = DatatypeFactory::STR2AT::createDerivedFromAtomicType(context->getMemoryManager(), typeUri, typeName, dmStringValue(context), context); return Sequence(item, context->getMemoryManager()); } } XERCES_CPP_NAMESPACE_QUALIFIER ComplexTypeInfo *cti = context->getDocumentCache()->getComplexTypeInfo(typeUri, typeName); if(cti) { if(cti->getContentType() == XERCES_CPP_NAMESPACE_QUALIFIER SchemaElementDecl::Simple) { XERCES_CPP_NAMESPACE_QUALIFIER DatatypeValidator *dtv = cti->getDatatypeValidator(); assert(dtv != 0); const Item *item = DatatypeFactory::STR2AT::createDerivedFromAtomicType(context->getMemoryManager(), dtv->getTypeUri(), dtv->getTypeLocalName(), dmStringValue(context), context); return Sequence(item, context->getMemoryManager()); } } if(cti) { if(cti->getContentType() == XERCES_CPP_NAMESPACE_QUALIFIER SchemaElementDecl::Empty) { return Sequence(context->getMemoryManager()); } if(cti->getContentType() == XERCES_CPP_NAMESPACE_QUALIFIER SchemaElementDecl::Mixed_Simple || cti->getContentType() == XERCES_CPP_NAMESPACE_QUALIFIER SchemaElementDecl::Mixed_Complex) { const Item *item = DatatypeFactory::STR2AT::createUntypedAtomic(context->getMemoryManager(), dmStringValue(context), context); return Sequence(item, context->getMemoryManager()); } if(cti->getContentType() == XERCES_CPP_NAMESPACE_QUALIFIER SchemaElementDecl::Children) { throw PathanException(XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathException::TYPE_ERR, X("Attempt to get typed value from a complex type with non-mixed complex content")); } } else { //throw error here?? Should not happen now, but if we stop giving anytype to invalid in DOMTypeInfo //then we will get here if its null. assert(false); } } else { /* XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer b; b.set(X("Attempt to get typed value from an element with no type information. Type name is ")); b.append(getTypeName()); b.append(X(",type uri is ")); b.append(getTypeURI()); b.append(X(",node name is ")); b.append(fNode->getNodeName()); b.append(X(", node uri is ")); b.append(fNode->getNamespaceURI()); throw PathanException(XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathException::TYPE_ERR, b.getRawBuffer() ); */ //return untypedatomic for now const Item *item = 0; item = DatatypeFactory::STR2AT::createUntypedAtomic(context->getMemoryManager(), dmStringValue(context), context); return Sequence(item, context->getMemoryManager()); } } break; case XERCES_CPP_NAMESPACE_QUALIFIER DOMXPathNamespace::XPATH_NAMESPACE_NODE: case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::DOCUMENT_NODE: case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TEXT_NODE: { const XMLCh *stringValue = dmStringValue(context); const Item *untypedAtomic = DatatypeFactory::STR2AT::createUntypedAtomic(context->getMemoryManager(), stringValue, context); return Sequence(untypedAtomic, context->getMemoryManager()); } break; case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::COMMENT_NODE: case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::PROCESSING_INSTRUCTION_NODE: { const XMLCh *stringValue = dmStringValue(context); const Item *untypedAtomic = DatatypeFactory::STR2AT::createString(context->getMemoryManager(), stringValue, context); return Sequence(untypedAtomic, context->getMemoryManager()); } break; } return Sequence(context->getMemoryManager()); } Sequence NodeImpl::dmDocumentURI(const DynamicContext* context) const { const XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* doc; const XMLCh* docURI; const XMLCh* prefix; switch (fNode->getNodeType()) { case XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::DOCUMENT_NODE : doc = (const XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *)fNode; docURI = doc->getDocumentURI(); prefix = XPath2NSUtils::getPrefix(docURI, context->getMemoryManager()); if (!XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(prefix, XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString)) { return Sequence(DatatypeFactory::STR2AT::createString(context->getMemoryManager(), docURI, context), context->getMemoryManager()); } else { return Sequence(context->getMemoryManager()); } default : return Sequence(context->getMemoryManager()); } } Sequence NodeImpl::dmType(const DynamicContext* context) const { if(fNode->getNodeType() != XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE && fNode->getNodeType() != XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ATTRIBUTE_NODE || fNode->getNodeType() != XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TEXT_NODE) { return Sequence(context->getMemoryManager()); } //otherwise return the Qname for the node return Sequence(DatatypeFactory::STR2AT::createQName(context->getMemoryManager(), getTypeName(), getTypeURI(), context), context->getMemoryManager()); } bool NodeImpl::lessThan(const Node* other) const { const NodeImpl* otherImpl = (const NodeImpl*)other; short pos = const_cast(fNode)->compareTreePosition(const_cast(otherImpl->fNode)); // compareTreePosition returns the position of the other node, compared to my position; so, if it sets the bit // TREE_POSITION_FOLLOWING, it means that we come before it if(pos & XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TREE_POSITION_FOLLOWING) return true; if(pos & XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TREE_POSITION_PRECEDING) return false; if(pos & XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TREE_POSITION_SAME_NODE) return false; // if the two nodes are attributes or namespaces, we get that they are equivalent; we need a stable ordering, so // we resort to comparing their pointers (we could even decide to sort them on their names...) if(pos & XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TREE_POSITION_EQUIVALENT) return fNode < otherImpl->fNode; // if we get they are disconnected, it could be they belong to different documents; in this case, order them according // to the pointer of their documents (all the nodes in document A must come before or after all the nodes in document B, // regardless of the chosen ordering criteria) // If they belong to the same document, they are floating, or maybe just one of them is floating; let's state we consider // the one connected coming before the disconnected one, and, if both are disconnected, we compare the two roots if(pos == XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TREE_POSITION_DISCONNECTED) { if(fNode->getOwnerDocument()!=otherImpl->fNode->getOwnerDocument()) return fNode->getOwnerDocument()fNode->getOwnerDocument(); else { const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* root1=FunctionRoot::root(fNode); const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* root2=FunctionRoot::root(otherImpl->fNode); if(root1==fNode->getOwnerDocument()) return true; else return root1fNode == ((const NodeImpl*)other)->fNode); } const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* NodeImpl::getDOMNode() const { return fNode; } bool NodeImpl::hasTypeInfo() const { const XMLCh *typeName=0; if (fNode->getNodeType() == XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE) { const XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *domElement = static_cast(fNode); typeName = domElement->getTypeInfo()->getName(); } else if (fNode->getNodeType() == XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ATTRIBUTE_NODE) { const XERCES_CPP_NAMESPACE_QUALIFIER DOMAttr *domAttr = static_cast(fNode); typeName = domAttr->getTypeInfo()->getName(); } else if(fNode->getNodeType() != XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TEXT_NODE) { typeName = ATUntypedAtomic::fgDT_UNTYPEDATOMIC; } return typeName == 0 ? false : true; } const XMLCh* NodeImpl::getTypeName() const { const XMLCh* typeName = 0; if (fNode->getNodeType() == XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE) { const XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *domElement = static_cast(fNode); typeName = domElement->getTypeInfo()->getName(); } else if (fNode->getNodeType() == XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ATTRIBUTE_NODE) { const XERCES_CPP_NAMESPACE_QUALIFIER DOMAttr *domAttr = static_cast(fNode); const XERCES_CPP_NAMESPACE_QUALIFIER DOMTypeInfo* pInfo=domAttr->getTypeInfo(); // If the [attribute type] property has one of the following values: ID, IDREF, IDREFS, ENTITY, ENTITIES, NMTOKEN, or NMTOKENS, // the type is an xs:QName with the [attribute type] as the local name and "http://www.w3.org/2001/XMLSchema" as the namespace name. if(pInfo->getNamespace()==NULL) // probably DTD validation was used { const XMLCh* szName=pInfo->getName(); if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDRefString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDRefsString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgEntityString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgEntitiesString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgNmTokenString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgNmTokensString)) typeName = szName; else typeName = ATUntypedAtomic::fgDT_UNTYPEDATOMIC; } else if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(pInfo->getNamespace(),XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(pInfo->getName(),XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_ANYSIMPLETYPE)) typeName = ATUntypedAtomic::fgDT_UNTYPEDATOMIC; else typeName = pInfo->getName(); } else if(fNode->getNodeType() != XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::TEXT_NODE) { typeName = ATUntypedAtomic::fgDT_UNTYPEDATOMIC; } else { DSLthrow(ItemException, X("NodeImpl::getTypeName"), X("Tried to get Type Name on Node other than DOMElement, DOMAttribute or DOMText")); } if(typeName) { return typeName; } if(!uniqueTypeName) { //lazily set data static unsigned int fUniqueTypeCount=1; static const XMLCh fPat[] = { XERCES_CPP_NAMESPACE_QUALIFIER chLatin_P, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_A, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_T, XERCES_CPP_NAMESPACE_QUALIFIER chNull}; XMLCh anonCountStr[16]; // a count of 15 digits should be enough XERCES_CPP_NAMESPACE_QUALIFIER XMLBuffer b(1023, getMemoryManager()); XERCES_CPP_NAMESPACE_QUALIFIER XMLString::binToText(fUniqueTypeCount++, anonCountStr, 15, 10); b.set(fPat); b.append(anonCountStr); uniqueTypeName = getMemoryManager()->getPooledString(b.getRawBuffer()); } return uniqueTypeName; } const XMLCh* NodeImpl::getTypeURI() const { if (fNode->getNodeType() == XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ELEMENT_NODE) { const XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *domElement = static_cast(fNode); return domElement->getTypeInfo()->getNamespace(); } else if (fNode->getNodeType() == XERCES_CPP_NAMESPACE_QUALIFIER DOMNode::ATTRIBUTE_NODE) { const XERCES_CPP_NAMESPACE_QUALIFIER DOMAttr *domAttr = static_cast(fNode); const XERCES_CPP_NAMESPACE_QUALIFIER DOMTypeInfo* pInfo=domAttr->getTypeInfo(); // If the [attribute type] property has one of the following values: ID, IDREF, IDREFS, ENTITY, ENTITIES, NMTOKEN, or NMTOKENS, // the type is an xs:QName with the [attribute type] as the local name and "http://www.w3.org/2001/XMLSchema" as the namespace name. if(pInfo->getNamespace()==NULL) // probably DTD validation was used { const XMLCh* szName=pInfo->getName(); if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDRefString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDRefsString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgEntityString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgEntitiesString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgNmTokenString) || XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(szName,XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgNmTokensString)) return XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA; else return FunctionConstructor::XMLChXPath2DatatypesURI; } else if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(pInfo->getNamespace(),XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(pInfo->getName(),XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_ANYSIMPLETYPE)) return FunctionConstructor::XMLChXPath2DatatypesURI; return pInfo->getNamespace(); } else { DSLthrow(ItemException, X("NodeImpl::getTypeURI"), X("Tried to get Type URI on Node other than DOMElement or DOMAttribute")); } }