我已经问过这个问题,并且我采取了错误的示例列表,这导致了没有用的答案。然后我以为我已经找到了解决方案,但它导致了错误的结果。那我再问一下吧。
Start XML 是一个列表,其中包含许多出现的 different 元素,这些元素具有包含 different 值的 different 属性。 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>
结果应该是一个列表,其中包含每个元素+属性+值组合仅出现一次并且应按以下顺序按字母顺序排序:
结果示例:
<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>
非常欢迎任何帮助,对于第一次尝试中的误导性问题深表歉意!
假设 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])"
。
这些建议假设元素可以具有不同的属性,但每个元素只有一个属性。