我有以下输入 XML 片段
<Customer>
<FirstName>ABC</FirstName>
<LastName>XYZ</LastName>
<Location>LOC_1</Location>
<Location>LOC_2</Location>
</Customer>
<Customer>
<FirstName>ABC</FirstName>
<LastName>XYZ</LastName>
<Location>LOC_1</Location>
</Customer>
<Customer>
<FirstName>SOME_OTHER_CUSTOMER</FirstName>
<LastName>XYZ</LastName>
<Location>LOC_1</Location>
</Customer>
我想从上述 XML 中过滤第二个节点,因为它具有相同的
FirstName
(ABC)、LastName
(XYZ),并且使用 XSLT 2.0 与第一个节点的 Location
(LOC_1) 之一相匹配。
输出XML
<Customer>
<FirstName>ABC</FirstName>
<LastName>XYZ</LastName>
<Location>LOC_1</Location>
<Location>LOC_2</Location>
</Customer>
<Customer>
<FirstName>SOME_OTHER_CUSTOMER</FirstName>
<LastName>XYZ</LastName>
<Location>LOC_1</Location>
</Customer>
我查看了一些使用
preceding-sibling
的示例,这些示例使用单个元素值来验证它是否重复,但不知何故,我无法使其适用于我检查多个/重复字段以检查重复项的场景。
非常感谢任何在 XSLT 中实现此功能的帮助/建议!
您的帖子提到了 XSLT 2,因为以前的 XSLT 2 处理器的当前版本(如如今的 Saxon 8.9-9.7(自 9.8 起))是 XSLT 3 处理器我首先展示 XSLT 3 解决方案
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-skip"/>
<xsl:template match="Customers">
<xsl:for-each-group select="Customer" composite="yes" group-by="LastName, FirstName">
<xsl:copy>
<xsl:copy-of select="FirstName, LastName"/>
<xsl:for-each-group select="current-group()/Location" group-by=".">
<xsl:copy-of select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
如果您使用的旧版本处理器确实只支持 XSLT 2 但不支持 3,那么请删除
xsl:mode
声明并使用分组作为
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:template match="Customers">
<xsl:for-each-group select="Customer" group-by="concat(LastName, '|', FirstName)">
<xsl:copy>
<xsl:copy-of select="FirstName, LastName"/>
<xsl:for-each-group select="current-group()/Location" group-by=".">
<xsl:copy-of select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
我假设
Customer
元素位于公共父元素 Customers
中,根据您的输入元素结构,您需要将匹配模式中的名称调整为真实的父元素名称,或者,如果元素没有对于单个共同父级,请使用更广泛的选择,例如 select="//Customer"
作为外部 for-each-group
。