问题
Need help in removing the duplicate node from the input xml using XSLT
This is how my XML looks like,
<?xml version="1.0"?>
<NodeA NodeAattr="123">
<NodeB NodeBattr="456"></NodeB>
<NodeC>
<NodeD="ValueD">
<NodeE Name="ValueABC">
<NodeF Value="0"></NodeF >
</NodeE >
<NodeE Name="ValueABC">
<NodeF Value="0"></NodeF >
</NodeE>
</NodeD>
</NodeC>
</NodeA>
My final output should look like
<NodeA NodeAattr="123">
<NodeB NodeBattr="456"></NodeB>
<NodeC>
<NodeD="ValueD">
<NodeE Name="ValueABC">
<NodeF Value="0"></NodeF>
</NodeE >
</NodeD>
</NodeC>
</NodeA>
Here the Name attribute of Node E has duplicate values. Based on this attribute I need to eliminate the duplicate.
It would be really helpful if someone could help me with the XSLT required here to get the output. I can only use the XSLT 1.0
回答1:
If two <NodeE>
elements are considered duplicates only if they have the same parent, this is probably the simplest solution:
Input
<?xml version="1.0"?>
<NodeA NodeAattr="123">
<NodeB NodeBattr="456"></NodeB>
<NodeC>
<NodeD Name="ValueD">
<NodeE Name="ValueABC">
<NodeF Value="0"></NodeF>
</NodeE>
<NodeE Name="ValueABC">
<NodeF Value="0"></NodeF>
</NodeE>
</NodeD>
<!-- Added another <NodeD> element for demonstration -->
<NodeD>
<NodeE Name="ValueABC">
<NodeF Value="0"></NodeF>
</NodeE>
<NodeE Name="ValueDEF">
<NodeF Value="0"></NodeF>
</NodeE>
</NodeD>
</NodeC>
</NodeA>
Stylesheet #1
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!--
Identity transform: copy elements and attributes from input file as is
-->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<!--
Drop <NodeE> elements with a preceding <NodeE> sibling that has the same
@Name attribute value as the current element
-->
<xsl:template
match="NodeE[preceding-sibling::NodeE[@Name = current()/@Name]]"/>
</xsl:stylesheet>
Output #1
<?xml version="1.0" encoding="utf-8"?>
<NodeA NodeAattr="123">
<NodeB NodeBattr="456"/>
<NodeC>
<NodeD Name="ValueD">
<NodeE Name="ValueABC">
<NodeF Value="0"/>
</NodeE>
</NodeD>
<NodeD>
<NodeE Name="ValueABC">
<NodeF Value="0"/>
</NodeE>
<NodeE Name="ValueDEF">
<NodeF Value="0"/>
</NodeE>
</NodeD>
</NodeC>
</NodeA>
On the other hand, if <NodeE>
elements should be considered duplicates across the whole document, you can use Muenchian grouping:
Stylesheet #2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kNode" match="NodeE" use="@Name"/>
<!--
Identity transform: copy elements and attributes from input file as is
-->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<!--
Use Muenchian grouping to apply unique NodeE elements.
See http://www.jenitennison.com/xslt/grouping/muenchian.html
-->
<xsl:template match="NodeE[generate-id() =
generate-id(key('kNode', @Name)[1])]">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<!-- Drop other <NodeE> elements -->
<xsl:template match="NodeE"/>
</xsl:stylesheet>
Output #2
<?xml version="1.0" encoding="utf-8"?>
<NodeA NodeAattr="123">
<NodeB NodeBattr="456"/>
<NodeC>
<NodeD Name="ValueD">
<NodeE Name="ValueABC">
<NodeF Value="0"/>
</NodeE>
</NodeD>
<NodeD>
<NodeE Name="ValueDEF">
<NodeF Value="0"/>
</NodeE>
</NodeD>
</NodeC>
</NodeA>
回答2:
Use "deep-euql" function to compare two item(). Check this one:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output indent="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="NodeE">
<xsl:choose>
<xsl:when test="deep-equal(self::NodeE, following-sibling::NodeE)"/>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="* | @*"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
来源:https://stackoverflow.com/questions/15924211/xsl-remove-the-duplicate-node-but-keep-the-original