我有一个名为filt
的变量,它包含一个像这样的xml:
<filters>
<ISP_WebItem FILTER="Farve" FILTERNAME="Transparent" UNITCODE="" />
<ISP_WebItem FILTER="Antal" FILTERNAME="10" UNITCODE="mapper" />
<ISP_WebItem FILTER="Indpakning" FILTERNAME="Æske" UNITCODE="" />
<ISP_WebItem FILTER="Materiale" FILTERNAME="PP" UNITCODE="" />
<ISP_WebItem FILTER="Bredde" FILTERNAME="35.6" UNITCODE="cm" />
<ISP_WebItem FILTER="Farve" FILTERNAME="blue" UNITCODE="" />
<ISP_WebItem FILTER="Dybde" FILTERNAME="5" UNITCODE="mm" />
<ISP_WebItem FILTER="Farve" FILTERNAME="red" UNITCODE="" />
</filters>
我想通过'FILTER'属性对这些元素进行分组。 那就是我想要一个像这样的输出xml(请注意xml元素是由过滤器属性重新排列的,即所有带有FILTER的元素现在都在相邻的位置)
<filters>
<ISP_WebItem FILTER="Farve" FILTERNAME="Transparent" UNITCODE="" />
<ISP_WebItem FILTER="Farve" FILTERNAME="blue" UNITCODE="" />
<ISP_WebItem FILTER="Farve" FILTERNAME="red" UNITCODE="" />
<ISP_WebItem FILTER="Antal" FILTERNAME="10" UNITCODE="mapper" />
<ISP_WebItem FILTER="Indpakning" FILTERNAME="Æske" UNITCODE="" />
<ISP_WebItem FILTER="Materiale" FILTERNAME="PP" UNITCODE="" />
<ISP_WebItem FILTER="Bredde" FILTERNAME="35.6" UNITCODE="cm" />
<ISP_WebItem FILTER="Dybde" FILTERNAME="5" UNITCODE="mm" />
</filters>
我尝试过这样的事情:
<xsl:variable name="grouped_filt" select="$filt//ISP_WebItem[@FILTER = preceding-sibling::*[1]/@FILTER ]"></xsl:variable>
但没有用。我无法在此找到任何错误。有人可以帮忙吗?
答案 0 :(得分:1)
XSLT 1.0中的标准方法称为Muenchian Grouping:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes" />
<xsl:key name="itemByFilter" match="ISP_WebItem" use="@FILTER" />
<xsl:template match="filters">
<filters>
<xsl:apply-templates select="ISP_WebItem[
generate-id() = generate-id(key('itemByFilter', @FILTER)[1])]" />
</filters>
</xsl:template>
<xsl:template match="ISP_WebItem">
<xsl:copy-of select="key('itemByFilter', @FILTER)" />
</xsl:template>
</xsl:stylesheet>
generate-id() = generate-id(key('itemByFilter', @FILTER)[1])
是一种仅使用每个ISP_WebItem
值选择第一个 FILTER
元素的方法,并将ISP_WebItem
模板应用于该元素。在模板中,我们然后复制具有相同FILTER
值的所有元素。
编辑:
您说<filters>
元素位于“名为filt的变量”中,而不是您直接从输入文档中匹配的内容。在这种情况下,您可以使用相同的键定义
<xsl:key name="itemByFilter" match="ISP_WebItem" use="@FILTER" />
但您使用<xsl:template match="filters">
代替<xsl:for-each select="$filt/filters">
。如果filt
变量是结果树片段而不是节点集 - 即它是创建为
<xsl:variable name="filt">
<filters>
<!-- ... -->
</filters>
</xsl:variable>
您将需要一个扩展功能将其重新转换为节点集
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:exslt="http://exslt.org/common"
exclude-result-prefixes="exslt">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes" />
<xsl:key name="itemByFilter" match="ISP_WebItem" use="@FILTER" />
<xsl:variable name="filt">
<filters>
<ISP_WebItem FILTER="Farve" FILTERNAME="Transparent" UNITCODE="" />
<ISP_WebItem FILTER="Antal" FILTERNAME="10" UNITCODE="mapper" />
<ISP_WebItem FILTER="Farve" FILTERNAME="blue" UNITCODE="" />
</filters>
</xsl:variable>
<xsl:variable name="grouped_filt">
<xsl:for-each select="exslt:node-set($filt)/filters">
<filters>
<xsl:apply-templates select="ISP_WebItem[
generate-id() = generate-id(key('itemByFilter', @FILTER)[1])]" />
</filters>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<!-- Demonstrate that the grouping did the right thing -->
<xsl:copy-of select="$grouped_filt" />
</xsl:template>
<xsl:template match="ISP_WebItem">
<xsl:copy-of select="key('itemByFilter', @FILTER)" />
</xsl:template>
</xsl:stylesheet>
此样式表在任何输入文档(例如<foo/>
)上运行时都会输出
<?xml version="1.0"?>
<filters>
<ISP_WebItem FILTER="Farve" FILTERNAME="Transparent" UNITCODE=""/>
<ISP_WebItem FILTER="Farve" FILTERNAME="blue" UNITCODE=""/>
<ISP_WebItem FILTER="Antal" FILTERNAME="10" UNITCODE="mapper"/>
</filters>