我需要删除以下xml中的重复项:
<ListOfRowIDWithListOfBooks xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/">
<RowIDWithListOfBooks>
<Row_ID>ADOA-XssK</Row_ID>
<ListOfBookInfo>
<book>
<BookType>Brand</BookType>
<BookName>jon</BookName>
</book>
<book>
<BookType>Brand</BookType>
<BookName>jon</BookName>
</book>
</ListOfBookInfo>
</RowIDWithListOfBooks>
</ListOfRowIDWithListOfBooks>
有人可以帮忙吗?
答案 0 :(得分:6)
使用标准分组解决方案可以轻松实现此任务。不要使用单个select语句来做那些众所周知会导致性能问题的语句。
注意对identity.xsl
的引用只是在样式表中包含众所周知的identity transformation模板。
[XSLT 1.0]
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="k-books" match="book" use="concat(BookType,'|',BookName)"/>
<xsl:include href="identity.xsl"/>
<xsl:template match="ListOfBookInfo">
<ListOfBookInfo>
<xsl:copy>
<xsl:apply-templates select="book
[generate-id()
=generate-id(key('k-books',concat(BookType,'|',BookName))[1])]"/>
</xsl:copy>
</ListOfBookInfo>
</xsl:template>
</xsl:stylesheet>
[XSLT 2.0]
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="identity.xsl"/>
<xsl:template match="ListOfBookInfo">
<ListOfBookInfo>
<xsl:for-each-group select="book"
group-by="concat(BookType,'|',BookName)">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</ListOfBookInfo>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:2)
试试这个XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="//ListOfBookInfo/book[not(BookType = preceding-sibling::book/BookType
and BookName = preceding-sibling::book/BookName)]"/>
</xsl:template>
<xsl:template match="book">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
它将选择具有唯一book
和BookType
的{{1}}个。在您的示例中,结果应为:
BookName
答案 2 :(得分:0)
您需要使用Muenchian分组方法将它们组合在一起。或xslt 2.0中更具体的分组功能。以下是两个相关的堆栈溢出问题:
答案 3 :(得分:0)
如果您对如何使用Muenchian Grouping(这是XSLT中的常用技术)实现这一目标感兴趣,首先需要定义一个“键”来识别行中的重复书籍。
<xsl:key
name="books"
match="book"
use="concat(concat(../../Row_ID, '#'), concat(concat(BookType, '#'), BookName))" />
在此我使用 RowID , BookType 和 BookName 的连锁键实现此目的。该密钥将包含所有具有该特定键值的书籍列表。请注意使用#字符作为连接字符。如果#出现在XML中,则需要选择另一个字符(或字符串)。
现在,当您在图书元素上进行匹配时,您可以检查是否有重复项
<xsl:variable
name="lookup"
select="concat(concat(../../Row_ID, '#'), concat(concat(BookType, '#'), BookName))" />
<xsl:if test="generate-id() = generate-id(key('books', $lookup)[1])">
换句话说,这个 book 元素是我们键中的第一个元素。
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key
name="books"
match="book"
use="concat(concat(../../Row_ID, '#'), concat(concat(BookType, '#'), BookName))"/>
<xsl:template match="book">
<xsl:variable name="lookup" select="concat(concat(../../Row_ID, '#'), concat(concat(BookType, '#'), BookName))"/>
<xsl:if test="generate-id() = generate-id(key('books', $lookup)[1])">
<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:stylesheet>
还要注意使用身份转换,以便可以复制其他节点而无需显式引用它们。将此XSLT应用于输入时,将生成以下输出:
<RowIDWithListOfBooks xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/">
<Row_ID>ADOA-XssK</Row_ID>
<ListOfBookInfo>
<book>
<BookType>Brand</BookType>
<BookName>jon</BookName>
</book>
</ListOfBookInfo>
</RowIDWithListOfBooks>
编辑:我修改了XSLT以删除不必要的模板匹配。