user1585862
user1585862

Reputation: 3

XSLT XML to XML selecting specific node

I am trying to transform a pretty complex XML file to XML via XSLT so it will be a replica of the previous XML document only with the second grandchild node excluded in the output. Hoping there is an easy solution using XSLT.

Here is a sample of the XML I'm trying to transform:

<cases>
    <Parent>
        <text1>Text1</text1>
        <text2>Text2</text2>
        <text3>Text3</text3>
        <Child_node>
             <Grandchild_node>
                 <gctext1>Sample text 1</gctext1>
                 <gctext2>Sample text 2</gctext2>
                 <gctext3>Sample text 3</gctext3>
                 <Great_grandchild_node>
                     <ggctext1>Great grandchild text 1</ggctext1>
                 </Great_grandchild_node>
             </Grandchild_node>
             <Grandchild_node>
                 <gctext1>More Sample text 1</gctext1>
                 <gctext2>Different Sample text 2</gctext2>
                 <gctext3>More Sample text 3</gctext3>
                 <Great_grandchild_node>
                     <ggctext1>Great grandchild text 2</ggctext1>
                 </Great_grandchild_node>
             </Grandchild_node>
        </Child_node>
    </Parent>
</cases>

I want the output to display everything but the info contained in the second Grandchild_node. Example of output I want to achieve:

<cases>
    <Parent>
        <text1>Text1</text1>
        <text2>Text2</text2>
        <text3>Text3</text3>
        <Child_node>
             <Grandchild_node>
                 <gctext1>Sample text 1</gctext1>
                 <gctext2>Sample text 2</gctext2>
                 <gctext3>Sample text 3</gctext3>
                 <Great_grandchild_node>
                     <ggctext1>Great grandchild text 1</ggctext1>
                 </Great_grandchild_node>
             </Grandchild_node>
        </Child_node>
    </Parent>
</cases>

Any help would be appreciated.

Upvotes: 0

Views: 707

Answers (2)

Derek Hunziker
Derek Hunziker

Reputation: 13141

You should be able to use xsl:copy in conjunction with matching any nodes you would like to remove:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="node()">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Grandchild_node[2]|Grandchild_node[5]"></xsl:template>
</xsl:stylesheet>

Since you commented that there are some separate unique child_nodes you want to remove, you can include those in this list. Tim's solution of using position() works well for excluding ranges.

Upvotes: 2

Tim C
Tim C

Reputation: 70598

This can be achieved by adding an extra template match to the identity transform to simply match Grandchild_node elements that aren't in the first position

<xsl:template match="Grandchild_node[position() > 1]" />

So, given the following XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="Grandchild_node[position() > 1]" />

   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

When applied to your sample XML, the following is output

<cases>
   <Parent>
      <text1>Text1</text1>
      <text2>Text2</text2>
      <text3>Text3</text3>
      <Child_node>
         <Grandchild_node>
            <gctext1>Sample text 1</gctext1>
            <gctext2>Sample text 2</gctext2>
            <gctext3>Sample text 3</gctext3>
            <Great_grandchild_node>
               <ggctext1>Great grandchild text 1</ggctext1>
            </Great_grandchild_node>
         </Grandchild_node>
      </Child_node>
   </Parent>
</cases>

Upvotes: 2

Related Questions