XPath selection while excluding elements having certain attribute values
My first post here - it's a great site and I will certainly do my best to give back as much as I can.
I have seen different manifestations of this following question; however my attempts to resolve don't appear to work.开发者_Python百科
Consider this simple tree:
<root>
<div>
<p>hello</p>
<p>hello2</p>
<p><span class="bad">hello3</span></p>
</div>
</root>
I would like to come up with an XPath expression that will select all child nodes of "div", except for elements that have their "class" attribute equal to "bad".
Here is what I have tried:
/root/div/node()[not (@class='bad')]
... However this doesn't seem to work.
What am I missing here?
Cheers,
IsaacWhen testing your XPath here with the provided XML document, the XPath seems to be indeed selecting all child nodes that do not have an attribute class="bad"
- these are all the <p>
elements in the document.
You will note that the only child node that has such an attribute is the <span>
, which indeed does not get selected.
Are you expecting the p
node surrounding your span
not to be selected?
I have been working with XPath in a Java program I'm writing. If you want to select the nodes that don't have class="bad" (i.e. the <span>
nodes, but not the surrounding <p>
nodes), you could use:
/root/div/descendant::*[not (@class='bad')]
Otherwise, if you want to select the
nodes that don't have a child with class='bad', you can use something like the following:
/root/div/p/*[not (@class='bad')]/..
the ..
part selects the immediate parent node.
The identity transform just matches and copies everything:
<xsl:template match="@*|node()" >
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
But you add a null transform that more specifically matches the pattern you want to exclude:
<xsl:template match="span[@class='bad']" />
( you can also add a priority attrib if you want to be more explicit about which one has precedence. )
Welcome to SO, Isaac!
I'd try this:
/root/div/*[./*[@class != "bad"]]
this ought to select all child elements (*
) of the div
element that do not have a descendant element with a class
attribute that equals bad
.
Edit:
As per @Alejandros comment:
/root/div/*[not(*/@class "bad")]
精彩评论