XPath to get all child nodes (elements, comments, and text) without parent
I need an XPath to fetch all ChildNodes ( including Text Element, Comment Element & Child Elements ) without Parent Element. Any help
Sample Example:
<DOC>
<PRESENTEDIN>
<X>
First Text Node #1
<y> Y can Have Child Nodes #
<child> deep to it </child>
</y>
Second Text Node #2 <z/>
</X>
<EVTS>
<evt/>
<evt>
<mtg_descr> SAE 2006 World Congress & Exhibition </mtg_descr>
<sess_descr> Advanced Hybrid Vehicle Powertrains (Part 1 of 5) </sess_descr>
<loc> Detroit,MI,United States </loc>
<sess_prod_grp_cd> TSESS </sess_prod_grp_cd>
<sess_evt_name> P13 </sess_evt_name>
<sess_gen_num> 138352 </sess_gen_num>
<mtg_start_dt> 04/03/2006 </mtg_start_dt>
<mtg_end_dt> 04/06/2006 </mtg_end_dt>
<desig> CONGRESS-2006 </desig>
</evt>
</EVTS>
<EVTTYPE>PAPER</EVTTYPE>
<SUPERTECH>
<![CDATA[C8585]]>
</SUPERTECH>
</PRESENTEDIN>
XPATH TRIED
1. $doc/PRESENTEDIN/X
2. $doc/PRESENTEDIN/X/descendant::*
2. $doc/PRESENTEDIN/X/self::*
EXPECTED OUTPUT
First Text Node #1
<y> Y can Have Child Nodes #
<child> deep to it </child>
</y>
Second Text Node #2 <z/>
I DON'T WANT
<X>
First Text Node #1
<y> Y can Have Child Nodes #
<child> deep to it </child>
</y>
Second Text Node #2 <z/>
</X>
From the documentation of XPath ( http://www.w3.org/TR/xpath/#location-paths ):
child::*
selects all element children of the context node
child::text()
selects all text node children of the context node
child::node()
selects all the children of the context node, whatever their node type
So I guess your answer is:
$doc/PRESENTEDIN/X/child::node()
And if you want a flatten array of all nested nodes:
$doc/PRESENTEDIN/X/descendant::node()
Use this XPath expression:
/*/*/X/node()
This selects any node (element, text node, comment or processing instruction) that is a child of any X
element that is a grand-child of the top element of the XML document.
To verify what is selected, here is this XSLT transformation that outputs exactly the selected nodes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:copy-of select="/*/*/X/node()"/>
</xsl:template>
</xsl:stylesheet>
and it produces exactly the wanted, correct result:
First Text Node #1
<y> Y can Have Child Nodes #
<child> deep to it </child>
</y> Second Text Node #2
<z />
Explanation:
As defined in the W3 XPath 1.0 Spec, "
child::node()
selects all the children of the context node, whatever their node type." This means that any element, text-node, comment-node and processing-instruction node children are selected by this node-test.node()
is an abbreviation ofchild::node()
(becausechild::
is the primary axis and is used when no axis is explicitly specified).