Reputation: 515
I need to write XSLT for an xml which contains in below format.
<books>
<book>
<a>name</a>
<a>name</a>
<b>name</b>
<b>name</b>
</book>
</books>
I need to eliminate the duplicate child nodes in some conditions.
ie.. if previous node (element) is <a>
and current node (element) is also <a>
, Then one node should be removed.
output for the above be,
`<a>name</a>`
`<b>name</b>`
please help me to do this.
Upvotes: 0
Views: 457
Reputation: 30991
As I understood, you want to omit a leaf element (without children elements) if it has a previous sibling, which:
So the most intuitive solution (I think) is to write an empty template, matching just these nodes:
<xsl:template match="*[not(*)][preceding-sibling::*[1][not(*)]
[name() = current()/name()][text() = current()/text()]]"/>
A brief description of the match attribute:
*[not(*)]
- Every element without any child element (leaf element).[
- Start of the second predicate.
preceding-sibling::*[1]
- Take the first preceding sibling.[not(*)]
- It must not have any child element.[name() = current()/name()]
- It must have the same name as the
"starting" element.[text() = current()/text()]
- It must have the same text as the
"starting" element. ]
- End of the second predicate.Of course, the script must contain also an identity template.
For a working example, with a bit extended source, see http://xsltransform.net/jxN8Nqm
If requirement concerning the same text is not necessary, delete the respective predicate fragment.
Upvotes: 1
Reputation: 167706
In XSLT 2 or 3 you can easily group adjacent sibling elements by their node name with for-each-group select="*" group-adjacent="node-name()"
and simply output the first item in each group (which is equal to the context item .
):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="book">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="node-name()">
<xsl:copy-of select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/6qVRKw4/1
Upvotes: 2