XML snippet:
<AA>
<BB>foo</BB>
<CC>bar</CC>
<DD>baz</DD>
<EE>bar</EE>
</AA>
How do I select all the child nodes of <AA>
that have bar
as its contents? In the example above, I'd want to select <CC>
and <EE>
. I'm thinking the solution is something like:
<xsl:template match="AA">
<xsl:for-each select="???" />
</xsl:template>
Accepted Answer. For the div element with an id attribute of hero //div[@id='hero'] , these XPath expression will select elements as follows: //div[@id='hero']/* will select all of its children elements. //div[@id='hero']/img will select all of its children img elements.
The child axis indicates the children of the context node. If an XPath expression does not specify an axis, the child axis is understood by default. Since only the root node or element nodes have children, any other use will select nothing.
To get all child nodes of an element, you can use the childNodes property. This property returns a collection of a node's child nodes, as a NodeList object. By default, the nodes in the collection are sorted by their appearance in the source code. You can use a numerical index (start from 0) to access individual nodes.
childNodes returns nodes: Element nodes, text nodes, and comment nodes. Whitespace between elements are also text nodes.
One of the simplest solutions to the OP's question is the following XPath expression:
*/*[.='bar']
Do note, that no XSLT instruction is involved -- this is just an XPath expression, so the question could only be tagged XPath.
From here on, one could use this XPath expression in XSLT in various ways, such as to apply templates upon all selected nodes.
For example, below is an XSLT transformation that takes the XML document and produces another one, in which all elements - children of <AA>
whose contents is not equal to "bar"
are deleted:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="AA">
<xsl:copy>
<xsl:apply-templates select="*[. = 'bar']"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the original XML document:
<AA>
<BB>foo</BB>
<CC>bar</CC>
<DD>baz</DD>
<EE>bar</EE>
</AA>
the wanted result is produced:
<AA>
<CC>bar</CC>
<EE>bar</EE>
</AA>
Do note:
In a match pattern we typically do not need to specify an absolute XPath expression, but just a relative one, so the full XPath expression is naturally simplified to this match pattern:
*[. = 'bar']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With