0

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.

4
  • The answer you have selected is wrong -- it deletes the first, not the second Grandchild_node. The answer by @TimC is the correct one. Please, accept the correct answer. Commented Aug 9, 2012 at 1:28
  • @DimitreNovatchev, he commented that he's trying to remove specific unique nodes. I've updated my answer to be a bit more clear. Commented Aug 9, 2012 at 5:38
  • @DerekHunziker, Yes, I see one correction. However you are also referring to the non-existing Grandchild_node[5] -isn't this strange? Commented Aug 9, 2012 at 11:53
  • Why is that strange? It's an example, just as the XML source provided is. The point is clearly to demonstrate a technique, rather than provide a specific solution for a specific input document, which clearly isn't possible with only a sample XML document. Commented Aug 9, 2012 at 11:55

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I applied this and the output was blank. I should mention that there are some separate unique child_nodes that I didn't mention that I want to come along as well. Don't know if I need to modify anything based on their presence.
2

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>

2 Comments

I applied this and the output was blank. I should mention that there are some separate unique child_nodes that I didn't mention that I want to come along as well. Don't know if I need to modify anything based on their presence.
Disregard prior comment, works, didn't resave the XSLT file first. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.