使用XSLT相对于另一个XML重新排序XML数据

时间:2013-11-07 10:30:43

标签: xml xslt xslt-1.0

我有两个XSL变量,它们包含这样的数据 第一个items

 <values>
  <value>
    12635
  </value>
  <value>
    SD20
  </value>
  <value>
    2404
  </value>
   <value>
    3586877
  </value>
</values>

第二个syddata

    <syddata lastUpdated="07.11.2013 11:06 ">
  <data Varenummer="3586877" Varenavn="Liqudffid s" Brand="Georg Jensen" ></data>
  <data Varenummer="12635" Varenavn="tesr" Brand="Kähcddler" ></data>
  <data Varenummer="2404" Varenavn="uhjy" Brand="Pitcfrhstone" ></data>
  <data Varenummer="SD20" Varenavn="sfggh" Brand="dghgh" ></data>
</syddata>

我想根据syddata中的itemsvalue字段的顺序items订购Varenummersyddatasyddata字段相同我希望o使用它作为键,并且排序 <syddata lastUpdated="07.11.2013 11:06 "> <data Varenummer="12635" Varenavn="tesr" Brand="Kähcddler" ></data> <data Varenummer="SD20" Varenavn="sfggh" Brand="dghgh" ></data> <data Varenummer="2404" Varenavn="uhjy" Brand="Pitcfrhstone" ></data> <data Varenummer="3586877" Varenavn="Liqudffid s" Brand="Georg Jensen" ></data> </syddata>   预期输出将是这样的

<xsl:stylesheet
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxml="urn:schemas-microsoft-com:xslt"
  xmlns:XSLTHelper="urn:XSLTHelper"
   xmlns:exslt="http://exslt.org/common"
  xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" 
  exclude-result-prefixes=" msxsl msxml ">
  <xsl:output method="html" omit-xml-declaration="yes"/>
  <xsl:param name="currentPage"/>
  <xsl:template match="/">
        <xsl:variable name="items" select="umbraco.library:Split($textWithPipes, '|')"/>
        <xsl:variable name="syddata" select="XSLTHelper:GenerateData($productids)"/>
  </xsl:template>

</xsl:stylesheet>

我已将整个XSLT添加到此处,以了解工作流程

{{1}}

2 个答案:

答案 0 :(得分:2)

为了提高效率,我首先要定义一个(在任何<xsl:template>之外)

<xsl:key name="dataByNummer" match="data" use="@Varenummer" />

然后主模板可以简单地

<xsl:template match="/">
    <xsl:variable name="items" select="umbraco.library:Split($textWithPipes, '|')"/>
    <xsl:variable name="syddata" select="XSLTHelper:GenerateData($productids)"/>

    <xsl:element name="{name($syddata/*)}">
      <!-- copy attributes -->
      <xsl:sequence select="$syddata/*/@*" />
      <!-- copy data in the right order -->
      <xsl:sequence select="
          for $id in $items//value
          return key('dataByNummer', normalize-space($id), $syddata)" />
    </xsl:element>
</xsl:template>

如果它是XSLT 1.0,那将会更加繁琐,因为XPath 1.0中没有for表达式,而XSLT 1.0 key函数没有第三个参数。但它仍然可以使用嵌套的for-each标记和额外变量

以类似的方式完成
<xsl:template match="/">
    <xsl:variable name="items" select="umbraco.library:Split($textWithPipes, '|')"/>
    <xsl:variable name="syddata" select="XSLTHelper:GenerateData($productids)"/>

    <xsl:element name="{name($syddata/*)}">
      <!-- copy attributes -->
      <xsl:copy-of select="$syddata/*/@*" />
      <!-- copy data in the right order -->
      <xsl:for-each select="$items//value">
        <xsl:variable name="curValue" select="." />
        <xsl:for-each select="$syddata"><!-- switch focus for the key function -->
          <xsl:copy-of select="key('dataByNummer', normalize-space($curValue))" />
        </xsl:for-each>
      </xsl:for-each>
    </xsl:element>
</xsl:template>

内部for-each只是一次迭代,但重点是将“当前文档”切换为$syddata,以便key函数在其中查找data个元素而不是$items

答案 1 :(得分:2)

您可以在XSLT 2.0中进行排序:

<xsl:stylesheet
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxml="urn:schemas-microsoft-com:xslt"
  xmlns:XSLTHelper="urn:XSLTHelper"
   xmlns:exslt="http://exslt.org/common"
  xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" 
  exclude-result-prefixes=" msxml ">
  <xsl:output method="html" omit-xml-declaration="yes"/>
  <xsl:param name="currentPage"/>
  <xsl:template match="/">
        <xsl:variable name="items" select="umbraco.library:Split($textWithPipes, '|')"/>
        <xsl:variable name="syddata" select="XSLTHelper:GenerateData($productids)"/>

        <xsl:variable name="sorted">
          <xsl:apply-templates select="$syddata" mode="sort">
            <xsl:with-param name="values" select="$items/values/value/normalize-space()"/>
          </xsl:apply-templates>
        </xsl:variable>
        <xsl:copy-of select="$sorted"/>
  </xsl:template>

  <xsl:template match="syddata" mode="sort">
    <xsl:param name="values"/>
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:perform-sort select="data">
        <xsl:sort select="index-of($values, @Varenummer)"/>
      </xsl:perform-sort>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>