XPath to get all child nodes (elements, comments, and text) without parent

XmlXpath

Xml Problem Overview


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 &amp; 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>

Xml Solutions


Solution 1 - Xml

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()

Solution 2 - Xml

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:

  1. 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.

  2. node() is an abbreviation of child::node() (because child:: is the primary axis and is used when no axis is explicitly specified).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkadalamittaiView Question on Stackoverflow
Solution 1 - XmllinepoglView Answer on Stackoverflow
Solution 2 - XmlDimitre NovatchevView Answer on Stackoverflow