这是我的输入
<someAccounts>
<Account>
<type>ABC</type>
<number>123456789</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>BBC</type>
<number>234567890</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>CBC</type>
<number>345678900</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>DBC</type>
<number>999999999</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>FBC</type>
<number>999999999</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
</someAccounts>
这里有2个帐号对象,它们具有相同的编号。我想要消除具有相同数字(不只是一个)的帐户对象。基本上这应该是我的输出
<someAccounts>
<Account>
<type>ABC</type>
<number>123456789</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>BBC</type>
<number>234567890</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>CBC</type>
<number>345678900</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
</someAccounts>
我尝试使用此
<xsl:for-each>
<xsl:copy-of select="someAccounts/Account[number != current()/number]"/>
</xsl:for-each>
这只能消除重复的一个,但我需要删除这两个帐户,我该如何实现。请帮忙
答案 0 :(得分:2)
首先,您可能会在XSLT identity transform的基础上构建,以复制XML中的现有元素
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
这意味着您只需要编写一个模板来忽略具有重复数字元素的帐户元素。如果您想检查带有重复数字元素的帐户元素,那么您可以定义一个键来查找它们
<xsl:key name="account" match="Account" use="number" />
有了这个,你只需要这个简单的模板来忽略重复
<xsl:template match="Account[key('account', number)[2]]" />
即。如果至少有两个帐户元素具有相同的数字,请忽略帐户元素。
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- Key to look up Account elements by their number -->
<xsl:key name="account" match="Account" use="number" />
<!-- Ignore Account elements for which there are at least two with the same number -->
<xsl:template match="Account[key('account', number)[2]]" />
<!-- Copy all other elements as-is -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
以下XSLT 1.0生成所需的输出。它使用显式for-each
和if
结构。该密钥有助于查找由相同数字定义的帐户集。只复制一组大小。
<?xml version="1.0" encoding="UTF-8"?>
<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" />
<!-- create key to find the accounts given by a number -->
<xsl:key name="number_key" match="Account" use="number/text()"/>
<xsl:template match="/someAccounts">
<xsl:copy>
<xsl:for-each select="Account">
<!-- key('number_key', ./number) returns a set of accounts with a given number -->
<!-- the next if only copies if the this set has size = 1 -->
<xsl:if test="count(key('number_key', ./number)) = 1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在XSLT 2.0中,for-each-group
构造可用于确定组大小。方法的结构保持不变:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/someAccounts">
<xsl:copy>
<xsl:for-each-group select="Account" group-by="number">
<!-- current-group() returns a set of accounts with a given number -->
<!-- the next if only copies if the this set has size = 1 -->
<xsl:if test="count(current-group()) = 1">
<xsl:copy-of select="current-group()[1]"/>
</xsl:if>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:0)
这是另一个更简单的解决方案,基于这样的假设:number
元素的值在任何先前的 Account
中发生,那么Account
不是复制过来。基本上,这是使用这一个额外模板的身份转换:
<xsl:template match="Account[./number=preceding-sibling::*/number]"/>
在上面,我们匹配任何Account
元素,该元素的数字也出现在前一个兄弟中。如果是这样,什么也不做。其他一切都被复制了。
以下是完整代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="Account[./number=preceding-sibling::*/number]"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于OP中的输入XMl时,它给出:
<someAccounts>
<Account>
<type>ABC</type>
<number>123456789</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>BBC</type>
<number>234567890</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>CBC</type>
<number>345678900</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
<Account>
<type>DBC</type>
<number>999999999</number>
<productCode>011</productCode>
<packageCode>022</packageCode>
</Account>
</someAccounts>