Reputation: 1146
The idea is very similar to the one asked about in this question and probably many others.
However, instead of extracting childs, I'm interested in the whole trimmed node. That is, the common solution is using
//node/*[not(self::a)]
instead of
//node/*
I'm looking for a way to apply the same logic of excluding a certain named branch, but extracting the node from a higher level: //node
instead of //node/*
.
What would be the appropriate syntax for this? //node[not(//node/a)]
and similar doesn't seem to work.
example:
<root>
<some_wrapper>
<node>
<a>
<report key=1>
<text>t</text>
</report>
<report key=2>
<text>t</text>
</report>
</a>
<b>
<text>sample_text</text>
<value>1</value>
</b>
<c>
<text>sample_text</text>
<value>2</value>
</c>
</node>
</some_wrapper>
</root>
The goal is to find and select the whole node
section, like when using //node
, except that a
child should not be included in the selection.
//node/*[not(self::a)]
doesn't work, since it selects a list of childs in node, but not the whole node (if I'm using the terminology correctly).
Upvotes: 0
Views: 911
Reputation: 163262
XPath always selects nodes that are present in the input document, unchanged. If you want to select a node named N, then //N will select that node; it returns, in effect, a reference to the node in the source document. If that node has children in the source document, then selecting it isn't going to remove those children.
Note that the XPath expression doesn't actually select the children. Many tools and applications that use XPath display the nodes selected by an XPath expression by serializing the whole XML subtree of those nodes, but that's a decision of the calling application (it could equally well display the result as a path containing the ancestors of the node, e.g. /root[1]/someWrapper[1]/node[2]
.)
If you want to create a modified copy of part of the source document, you need XSLT or XQuery for that, not XPath.
Upvotes: 2
Reputation: 14135
Here is the xpath to get all nodes (except the a
) under some_wrapper
.
//some_wrapper/descendant::*[not(name()='a' or ancestor::a)]
If you want to filter only the items under node
tag then use the below.
//some_wrapper/descendant::*[not(name()='a' or ancestor::a) and (name()='node' or ancestor::node)]
Upvotes: 2