Given an XML document and an XPath expression, I want to create a new document which has all of the nodes of the original document with the exception of the nodes selected by the XPath expression, effectively giving the result of a subtract filter.
My idea was to use the xmlXpathEvalExpression()
function, and for each node in the root document tree, copy the node over unless the node matches the returned xmlNodeSet
. However, libxml2 gives no hints about how, or even if, nodes can be tested for equality.
Are you supposed to compare the pointers to the nodes in the returned set? Or are you supposed to compare the given node names/namespaces?
As mentioned in the comments, the node pointers returned from evaluating an XPath expression point directly to the nodes in the original document.[1] So you can simply call xmlUnlinkNode
on each node in the returned node set to remove it from the document. Then, in a second step, call xmlFreeNode
on each node to free the nodes. It's important to not call xmlFreeNode
before all nodes are unlinked.[2]
[1] Except for namespace nodes returned from the namespace axis namespace::*
with type XML_NAMESPACE_DECL
, but these are rarely used.
[2] It should work to immediately free each node if you iterate the node set in reverse order.