2

在 XSLT 中,我想调用一个模板,并将一些内容传递给一个模板。但是,内容应该按照视频的排序方式 (13-41-61) 进行排序,而不是按照内容的排序顺序 (61-41-13)。

我有以下 XML:

<videos>
    <video key="13" />
    <video key="41" />
    <video key="61" />
</videos>


<contents>
    <content key="61" />
    <content key="41" />
    <content key="13" />
    <content key="10" />
</contents>

XSLT:

<xsl:call-template name="video">
    <xsl:with-param name="content" select="contents/content[@key = videos/video/@key]" />
</xsl:call-template>

有没有办法轻松完成这项工作?

4

3 回答 3

1

这种转换似乎是当前发布的解决方案中最有效的——否count(preceding-sibling::*)和否//content[@key=$key]——两者都导致 O(N^2)——二次时间复杂度

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:key name="kContByAtttr" match="content" use="@key"/>
 <xsl:key name="kVidByAtttr" match="video" use="@key"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="contents">
  <contents>
   <xsl:for-each select="/*/videos/video">
     <xsl:apply-templates select="key('kContByAtttr', @key)"/>
   </xsl:for-each>
   <xsl:apply-templates select="*[not(key('kVidByAtttr', @key))]"/>
  </contents>
 </xsl:template>
</xsl:stylesheet>

当应用于提供的 XML(包装到单个顶部元素中以成为一个)文档时:

<t>
    <videos>
        <video key="13" />
        <video key="41" />
        <video key="61" />
    </videos>
    <contents>
        <content key="61" />
        <content key="41" />
        <content key="13" />
        <content key="10" />
    </contents>
</t>

产生想要的正确结果

<t>
   <videos>
      <video key="13"/>
      <video key="41"/>
      <video key="61"/>
   </videos>
   <contents>
      <content key="13"/>
      <content key="41"/>
      <content key="61"/>
      <content key="10"/>
   </contents>
</t>
于 2013-04-12T14:49:12.377 回答
0

是否有特定原因需要使用<xsl:call-template>吗?如果您只想按<content>元素所在的顺序对<video>元素进行排序,您可以执行以下操作:

样式表

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"
    omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>

  <!--
  Index <video> elements according to their position in the tree.
  See http://stackoverflow.com/a/5876074/825783
  -->
  <xsl:key name="kVideo" match="video"
    use="count(preceding-sibling::video) + 1"/>

  <!-- Identity transform -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="content">
    <xsl:copy>
      <!--
      Apply attributes (fallback to account for the extra <content> element)
      -->
      <xsl:apply-templates select="@*"/>
      <!--
      Apply the @key attribute of the <video> element that's in a
      position corresponding to the position of this <content> element
      -->
      <xsl:apply-templates select="key('kVideo', position())/@key"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

输入

<root>
  <videos>
    <video key="13"/>
    <video key="41"/>
    <video key="61"/>
  </videos>
  <contents>
    <content key="61"/>
    <content key="41"/>
    <content key="13"/>
    <content key="10"/>
  </contents>
</root>

输出

<root>
  <videos>
    <video key="13"/>
    <video key="41"/>
    <video key="61"/>
  </videos>
  <contents>
    <content key="13"/>
    <content key="41"/>
    <content key="61"/>
    <content key="10"/>
  </contents>
</root>
于 2013-04-12T11:37:22.660 回答
0

复制并粘贴我通常使用的代码片段,它应该可以工作

<xsl:template match="/">
  <contents>
    <xsl:for-each select="//video">
      <xsl:call-template name="sortedId">
        <xsl:with-param name="key" select="@key"></xsl:with-param>
      </xsl:call-template>
    </xsl:for-each>
  </contents>    
</xsl:template>


<xsl:template name="sortedId" >
    <xsl:param name="key"></xsl:param>
    <xsl:apply-templates select="//content[@key=$key]" />
</xsl:template>

<xsl:template match="content">
    <xsl:copy-of select="." />
</xsl:template>

结果是:

<contents>
  <content key="13" />
  <content key="41" />
  <content key="61" />
</contents>
于 2013-04-12T10:38:50.610 回答