Reputation: 3
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
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
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