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.
This commit is contained in:
jez 2008-05-28 08:53:21 +00:00
parent 5d7f3364ba
commit 53fbf26ff0
2 changed files with 82 additions and 47 deletions

View file

@ -408,7 +408,8 @@ public:
DOM::Node<string_type, string_adaptor> current = context;
if(current.getNodeType() != DOM::Node_base::ATTRIBUTE_NODE)
list_.push_back(DOM::Node<string_type, string_adaptor>(
new NamespaceNodeImpl<string_type, string_adaptor>(string_adaptor::construct_from_utf8("xml"),
new NamespaceNodeImpl<string_type, string_adaptor>(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<string_type, string_adaptor> attr = current.getAttributes().item(a);
if(attr.getPrefix() == xmlns_prefix_)
list_.push_back(DOM::Node<string_type, string_adaptor>(
new NamespaceNodeImpl<string_type, string_adaptor>(attr.getLocalName(),
new NamespaceNodeImpl<string_type, string_adaptor>(context,
attr.getLocalName(),
attr.getNodeValue())
)
);

View file

@ -20,72 +20,105 @@ namespace impl
{
template<class stringT, class string_adaptorT = Arabica::default_string_adaptor<stringT> >
class NamespaceNodeImpl : public Arabica::SimpleDOM::ChildlessNodeImpl<stringT, string_adaptorT>
class NamespaceNodeImpl : public DOM::Node_impl<stringT, string_adaptorT>
{
typedef Arabica::SimpleDOM::ChildlessNodeImpl<stringT, string_adaptorT> NodeT;
public:
NamespaceNodeImpl(stringT localname,
stringT value) :
Arabica::SimpleDOM::ChildlessNodeImpl<stringT, string_adaptorT>(0),
typedef DOM::Node<stringT, string_adaptorT> NodeT;
typedef DOM::Node_impl<stringT, string_adaptorT> NodeImplT;
typedef DOM::NodeList_impl<stringT, string_adaptorT> NodeListT;
typedef DOM::NamedNodeMap_impl<stringT, string_adaptorT> NamedNodeMapT;
typedef DOM::Document_impl<stringT, string_adaptorT> 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<stringT, string_adaptorT>* cloneNode(bool deep) const
{
return new NamespaceNodeImpl<stringT, string_adaptorT>(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<stringT, string_adaptorT>(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_;