mirror of
https://github.com/jezhiggins/arabica
synced 2024-12-26 21:58:39 +01:00
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:
parent
5d7f3364ba
commit
53fbf26ff0
2 changed files with 82 additions and 47 deletions
|
@ -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())
|
||||
)
|
||||
);
|
||||
|
|
|
@ -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_;
|
||||
|
|
Loading…
Reference in a new issue