From 53fbf26ff0f934a304fe7a0984baced4c99926dc Mon Sep 17 00:00:00 2001 From: jez <> Date: Wed, 28 May 2008 08:53:21 +0000 Subject: [PATCH] Correctly implemented Namespace Nodes. The XPath data model requires that namespace nodes are associated with an element, and sort ahead of attribute nodes in document order. Until now, Arabica's namespace node had no parent, or owner document and so was failing these requirements. The Xalan position111 test case highlights this requirement. --- include/XPath/impl/xpath_axis_enumerator.hpp | 6 +- include/XPath/impl/xpath_namespace_node.hpp | 123 ++++++++++++------- 2 files changed, 82 insertions(+), 47 deletions(-) diff --git a/include/XPath/impl/xpath_axis_enumerator.hpp b/include/XPath/impl/xpath_axis_enumerator.hpp index 89adb469..6567a4b5 100644 --- a/include/XPath/impl/xpath_axis_enumerator.hpp +++ b/include/XPath/impl/xpath_axis_enumerator.hpp @@ -408,7 +408,8 @@ public: DOM::Node current = context; if(current.getNodeType() != DOM::Node_base::ATTRIBUTE_NODE) list_.push_back(DOM::Node( - new NamespaceNodeImpl(string_adaptor::construct_from_utf8("xml"), + new NamespaceNodeImpl(context, + string_adaptor::construct_from_utf8("xml"), string_adaptor::construct_from_utf8("http://www.w3.org/XML/1998/namespace")) ) ); @@ -419,7 +420,8 @@ public: DOM::Node attr = current.getAttributes().item(a); if(attr.getPrefix() == xmlns_prefix_) list_.push_back(DOM::Node( - new NamespaceNodeImpl(attr.getLocalName(), + new NamespaceNodeImpl(context, + attr.getLocalName(), attr.getNodeValue()) ) ); diff --git a/include/XPath/impl/xpath_namespace_node.hpp b/include/XPath/impl/xpath_namespace_node.hpp index 52491975..ed210623 100644 --- a/include/XPath/impl/xpath_namespace_node.hpp +++ b/include/XPath/impl/xpath_namespace_node.hpp @@ -20,72 +20,105 @@ namespace impl { template > -class NamespaceNodeImpl : public Arabica::SimpleDOM::ChildlessNodeImpl +class NamespaceNodeImpl : public DOM::Node_impl { - typedef Arabica::SimpleDOM::ChildlessNodeImpl NodeT; public: - NamespaceNodeImpl(stringT localname, - stringT value) : - Arabica::SimpleDOM::ChildlessNodeImpl(0), + typedef DOM::Node NodeT; + typedef DOM::Node_impl NodeImplT; + typedef DOM::NodeList_impl NodeListT; + typedef DOM::NamedNodeMap_impl NamedNodeMapT; + typedef DOM::Document_impl DocumentImplT; + + NamespaceNodeImpl(const NodeT& parentNode, + const stringT& localname, + const stringT& value) : + NodeImplT(), + parentNode_(parentNode.underlying_impl()), localname_(localname), value_(value), ref_(0) { - this->setReadOnly(true); } // NamespaceNodeImpl virtual ~NamespaceNodeImpl() { } - /////////////////////////////////////////////////////// - // DOM::Node methods - virtual DOM::Node_base::Type getNodeType() const - { - return NAMESPACE_NODE_TYPE; - } // getNodeType - - virtual const stringT& getNodeName() const - { - return localname_; - } // getNodeName - - virtual const stringT& getNodeValue() const - { - return value_; - } // getNodeValue - - virtual const stringT& getNamespaceURI() const - { - return empty_; - } // getNamespaceURI() - - virtual const stringT& getPrefix() const - { - return empty_; - } // getPrefix - - virtual const stringT& getLocalName() const - { - return localname_; - } // getLocalName - - virtual DOM::Node_impl* cloneNode(bool deep) const - { - return new NamespaceNodeImpl(localname_, value_); - } // cloneNode - - // not part of the document, so need to manage our own lifetime + //////////////////////////////////////////////////////// + // not fully part of the document, so need to manage our own lifetime virtual void addRef() { + parentNode_->addRef(); ++ref_; } // addRef virtual void releaseRef() { + parentNode_->releaseRef(); if(!(--ref_)) delete this; } // releaseRef -private: + /////////////////////////////////////////////////////// + // DOM::Node methods + virtual const stringT& getNodeName() const { return localname_; } + + virtual const stringT& getNodeValue() const { return value_; } + virtual void setNodeValue(const stringT&) { oopsReadOnly(); } + + virtual DOM::Node_base::Type getNodeType() const { return NAMESPACE_NODE_TYPE; } + + virtual NodeImplT* getParentNode() const { return parentNode_; } + + virtual NodeListT* getChildNodes() const { return 0; } + + virtual NodeImplT* getFirstChild() const { return 0; } + virtual NodeImplT* getLastChild() const { return 0; } + + virtual NodeImplT* getPreviousSibling() const { return 0; } + virtual NodeImplT* getNextSibling() const { return 0; } + + virtual NamedNodeMapT* getAttributes() const { return 0; } + + virtual DocumentImplT* getOwnerDocument() const { return parentNode_->getOwnerDocument(); } + + virtual NodeImplT* insertBefore(NodeImplT* newChild, NodeImplT* refChild) { throw DOM::DOMException(DOM::DOMException::HIERARCHY_REQUEST_ERR); } + virtual NodeImplT* replaceChild(NodeImplT* newChild, NodeImplT* oldChild) { throw DOM::DOMException(DOM::DOMException::HIERARCHY_REQUEST_ERR); } + virtual NodeImplT* removeChild(NodeImplT* oldChild) { throw DOM::DOMException(DOM::DOMException::HIERARCHY_REQUEST_ERR); } + virtual NodeImplT* appendChild(NodeImplT* newChild) { throw DOM::DOMException(DOM::DOMException::HIERARCHY_REQUEST_ERR); } + virtual void purgeChild(NodeImplT* oldChild) { throw DOM::DOMException(DOM::DOMException::HIERARCHY_REQUEST_ERR); } + + virtual bool hasChildNodes() const { return false; } + + virtual NodeImplT* cloneNode(bool deep) const { return new NamespaceNodeImpl(parentNode_, localname_, value_); } + + virtual void normalize() { } + + virtual bool isSupported(const stringT& feature, const stringT& version) const { return false; } + + virtual const stringT& getNamespaceURI() const { return empty_; } + virtual const stringT& getPrefix() const { return empty_; } + virtual void setPrefix(const stringT&) { oopsReadOnly(); } + virtual const stringT& getLocalName() const { return localname_; } + + virtual bool hasNamespaceURI() const { return false; } + virtual bool hasPrefix() const { return false; } + + virtual bool hasAttributes() const { return false; } + + private: + void oopsReadOnly() const { throw DOM::DOMException(DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR); } + + NamespaceNodeImpl(NodeImplT* parentNode, + const stringT& localname, + const stringT& value) : + NodeImplT(), + parentNode_(parentNode), + localname_(localname), + value_(value), + ref_(0) + { + } // NamespaceNodeImpl + + NodeImplT* parentNode_; stringT localname_; stringT value_; const stringT empty_;