示例xml如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<check>
<val>
<Samsung>
<name value="galaxy"/>
<name value="galaxy"/>
<name value="galaxys"/>
<id value="123"/>
<id value="123"/>
<name2 value="galaxy"/>
</Samsung>
<htc>
<name value="galaxy"/>
<name value="galaxy"/>
<name value="galaxys"/>
<id value="123"/>
<id value="123"/>
<name2 value="galaxy"/>
</htc>
</val>
</check>
如何删除重复项?
带有匹配值的 <name>
和<id>
标签...如果还有除<Samsung>
和<htc>
以外的其他标签,如何在xslt中编写循环?我不知道怎么写xslt。请帮忙。
输出xml应如下所示:
<check>
<val>
<Samsung>
<name value="galaxy"/>
<name value="galaxys"/>
<id value="123"/>
<name2 value="galaxy"/>
</Samsung>
<htc>
<name value="galaxy"/>
<name value="galaxys"/>
<id value="123"/>
<name2 value="galaxy"/>
</htc>
</val>
</check>
答案 0 :(得分:2)
如果你能确保重复的节点总是连续的,那么最简单的方法就是建立在XSTL身份转换的基础上,只需要一个额外的模板去除模板就好了
<xsl:template
match="*[not(*)]
[name() = preceding-sibling::*[1]/name()]
[@value = preceding-sibling::*[1]/@value]" />
这匹配任何子元素,如果它与前一个元素具有相同的名称和值,则忽略它。在这种情况下,无需在任何地方对元素名称进行硬编码。
在这种情况下,这是完整的XSLT
<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 select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*)][name() = preceding-sibling::*[1]/name()][@value = preceding-sibling::*[1]/@value]" />
</xsl:stylesheet>
但是,如果您的XML看起来像这样,并且您的重复节点是连续的
,则会失败 <Samsung>
<name value="galaxy"/>
<name value="galaxys"/>
<id value="123"/>
<name value="galaxy"/>
<id value="123"/>
<name2 value="galaxy"/>
</Samsung>
您可以通过更改模板来检查所有以前的节点
来解决此问题<xsl:template match="*[not(*)]
[name() = preceding-sibling::*/name()]
[@value = preceding-sibling::*/@value]" />
然而,随着大量元素的出现,这开始变得效率低下。如果你有数百个元素,那么每个precedinig-sibling检查将重复涉及检查数百个元素(即第100个元素必须检查99个前面的元素,第101个元素检查100个元素等)。
更有效的方法(在XSLT1.0中)是使用一种名为Muenchian Grouping的技术。如果你经常使用XSLT,肯定值得学习。
首先,您定义一个键,以“组合”您的元素。在这种情况下,您正在寻找由其父元素名称和值
定义的不同元素<xsl:key name="duplicate" match="*[not(*)]" use="concat(generate-id(..), '|', name(), '|', @value)" />
然后忽略重复项,匹配给定'lookup'值的键中第一个位置没有出现的任何元素
<xsl:template match="*[not(*)]
[generate-id() !=
generate-id(key('duplicate', concat(generate-id(..), '|', name(), '|', @value))[1])]" />
在这种情况下,这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="duplicate" match="*[not(*)]" use="concat(generate-id(..), '|', name(), '|', @value)" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*)][generate-id() != generate-id(key('duplicate', concat(generate-id(..), '|', name(), '|', @value))[1])]" />
</xsl:stylesheet>
答案 1 :(得分:1)
进行此转换时
<?xml version='1.0'?>
<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 select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="name">
<xsl:if test="self::name/text()= following-sibling::name/text()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="name2">
<xsl:if test="self::name2/text()= following-sibling::name2/text()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
在XML 下面运行
<?xml version="1.0"?>
<check>
<val>
<sai>
<name> A</name>
<name> A</name>
<name2> B</name2>
<name2> B</name2>
</sai>
<dinesh>
<name> A</name>
<name> A</name>
<name2> B</name2>
<name2> B</name2>
</dinesh>
</val>
</check>
获取所需的输出
<?xml version='1.0' ?>
<check>
<val>
<sai>
<name> A</name>
<name2> B</name2>
</sai>
<dinesh>
<name> A</name>
<name2> B</name2>
</dinesh>
</val>
</check>
答案 2 :(得分:0)
与@ siva2012的回答差不多。但如果只有一个名字孩子,那就更正确了。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" />
<xsl:template match="name">
<xsl:variable name="text" select="text()"/>
<xsl:if test="not(following-sibling::name[text()= $text])" >
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
</xsl:stylesheet>