我已经问过这个问题了,我采用了一个错误的示例列表,这导致了无用的答案。然后我认为我找到了一个解决方案但它会导致错误的结果。所以让我再问一次。
启动XML是一个列表,其中包含许多不同元素的出现,这些元素具有不同的属性,其中包含不同的值。 示例XML:
<attributes>
<para role="tocmain1"/>
<para role="tocmain1"/>
<other style="fix"/>
<other style="fix1"/>
<para role="tocmain2"/>
<para role="tocmain2"/>
<para role="tocmain2"/>
<para role="tocmain3"/>
<para role="tocmain3"/>
<para language="de"/>
<para language="de"/>
<para role="tocmain3"/>
</attributes>
结果应该是一个列表,其中包含每个Element +属性+值组合只出现一次,并且应按此顺序按字母顺序排序:1。元素的字母顺序,2。字母顺序属性,3。按字母顺序排列的值。
示例结果:
<attributes>
<other style="fix"/>
<other style="fix1"/>
<para language="de"/>
<para role="tocmain1"/>
<para role="tocmain2"/>
<para role="tocmain3"/>
</attributes>
现在我正在使用连续执行的两个xlst,问题是结果列表不完整:缺少元素+属性+值的某些组合。问题位于第一个模板中,因为我按属性值分组,而我只采用第一个出现。可以是相同的属性值与不同的属性一起使用。在这些情况下,缺少第二次出现。是否有可能根据属性+值的组合进行分组?
1。 XSLT(分组和删除重复项):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*" group-by="@*">
<xsl:sort select="@*"/>
<xsl:apply-templates select="current-group()[1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
2。 XSLT(按字母顺序排序):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<attributes>
<xsl:for-each select="attributes/node()">
<xsl:sort select="name()" order="ascending"/>
<xsl:sort select="name(@*)" order="ascending"/>
<xsl:sort select="@*" order="ascending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</attributes>
</xsl:template>
</xsl:stylesheet>
任何帮助都是非常受欢迎的,并且在第一次尝试时对于误导性的问题感到抱歉!
答案 0 :(得分:1)
假设Saxon 9.7 PE或EE或AltovaXML 2017支持XSLT 3.0,您只需使用复合密钥:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
exclude-result-prefixes="xs math"
version="3.0">
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:for-each-group select="*" group-by="node-name(), node-name(@*[1]), @*[1]" composite="yes">
<xsl:sort select="string(current-grouping-key()[1])"/>
<xsl:sort select="string(current-grouping-key()[2])"/>
<xsl:copy-of select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
使用XSLT 2.0,您可以使用嵌套的for-each-group
s
<xsl:template match="/*">
<xsl:copy>
<xsl:for-each-group select="*" group-by="node-name(.)">
<xsl:sort select="string(current-grouping-key())"/>
<xsl:for-each-group select="current-group()" group-by="node-name(@*[1])">
<xsl:sort select="string(current-grouping-key())"/>
<xsl:for-each-group select="current-group()" group-by="@*[1]">
<xsl:copy-of select="."/>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
或使用使用字符串连接创建的复合密钥。 group-by="concat(node-name(), '|', node-name(@*[1]), '|', @*[1])"
。
这些建议假定元素可以具有不同的属性,但每个元素只有一个属性。