0

我有一个名为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>

我想按其“过滤器”属性对这些元素进行分组。那就是我想要这样的输出 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>

但没有用。我找不到任何错误。任何人都可以帮忙吗?

4

1 回答 1

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_WebItemFILTERISP_WebItemFILTER

编辑:

您说该<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>
于 2013-01-02T12:03:31.567 回答