如何在xslt中使用xsl:sort?

时间:2017-04-24 17:53:07

标签: xml sorting xslt xslt-1.0

我有一个包含两个<video>元素的XML文件。我的转换通过<videos>将这些元素合并为一个for-each元素,并将结果记录为变量variableA的值。

我可以根据原始数据中<v>元素的值对转换后的内容进行排序吗?

这是我的代码 http://xsltransform.net/pNmBxZH/8

输入xml

<test>
    <video graph="1" potime="1811">
        <sec>
            <secid>3812907</secid>
            <pick>
                <vdsecname>A</vdsecname>
                <mediadate>24 Apr 2017, 7:45PM IST</mediadate>
                <v>240420171945</v>

            </pick>
            <pick>
                <vdsecname>D</vdsecname>
                <mediadate>20 Apr 2017, 4:30PM IST</mediadate>
                <v>200420171630</v>
            </pick>
            <pick>
                <vdsecname>E</vdsecname>
                <mediadate>20 Apr 2017, 3:30PM IST</mediadate>
                 <v>200420171530</v>
            </pick>

        </sec>
    </video>
    <video graph="1" potime="94">
        <sec>
            <secid>20970242</secid>
            <pick>
                <vdsecname>B</vdsecname>
                <mediadate>23 Apr 2017, 7:30PM IST</mediadate>
                 <v>230420171930</v>
            </pick>
            <pick>
                <vdsecname>C</vdsecname>
                <mediadate>22 Apr 2017, 5:33PM IST</mediadate>
                 <v>220420171733</v>
            </pick>
        </sec>
    </video>
</test>

使用xsl:sort我想要变量variableAv标签中有值使用此值我要对变量进行排序

预期输出

 <videos>
        <pick>

            <vdsecname>A</vdsecname>

            <mediadate>24 Apr 2017, 7:45PM IST</mediadate>

            <v>240420171945</v>


        </pick>
        <pick>

            <vdsecname>B</vdsecname>

            <mediadate>23 Apr 2017, 7:30PM IST</mediadate>

            <v>230420171930</v>

        </pick>
        <pick>

            <vdsecname>C</vdsecname>

            <mediadate>22 Apr 2017, 5:33PM IST</mediadate>

            <v>220420171733</v>

        </pick>
        <pick>

            <vdsecname>D</vdsecname>

            <mediadate>20 Apr 2017, 4:30PM IST</mediadate>

            <v>200420171630</v>

        </pick>
        <pick>

            <vdsecname>E</vdsecname>

            <mediadate>20 Apr 2017, 3:30PM IST</mediadate>

            <v>200420171530</v>

        </pick>

    </videos>

我希望<pick>中生成的<videos>元素按其<v>子项(从输入文档中复制)的降序排序,如图所示。

这是我目前的转型:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:template match="/">
      <hmtl>
        <head>
          <title>New Version!</title>
        </head>
        <xsl:variable name="variableA">
          <videos>

            <xsl:for-each select="test/video">
              <xsl:copy-of select="sec/pick"/>
            </xsl:for-each>
          </videos>
        </xsl:variable>
        <xsl:copy-of select="$variableA"/>
      </hmtl>
    </xsl:template>

</xsl:transform>

2 个答案:

答案 0 :(得分:0)

可以稍微调整一下for-each和sort会有所帮助。请告诉我们。

         <xsl:for-each select="test/video/sec/pick">
            <xsl:sort select="vdsecname" data-type="text" order="ascending"/>
            <xsl:copy-of select="."/>
          </xsl:for-each>

答案 1 :(得分:0)

您当然可以使用xsl:sort来生成所需的输出。既然你知道这个元素,但仍然会问这个问题,我想你试图使用它但却没有得到你想要的结果。鉴于样式表的当前结构,这不足为奇。

要理解xsl:sort最重要的事情之一是它导致排序的原因,这是apply-templates或{{1}选择的输入节点与之关联的元素。 for-each导致输入节点按其描述的顺序进行处理,上下文的当前节点列表也以这种方式排序。这是您编写的样式表的问题,因为它是您要排序的xsl-sort元素,而是您要迭代的<pick>元素。

此外,目前还不清楚为什么要在这里引入变量。我怀疑你有误解,你可能会在设置它们之后对该变量的内容进行排序,但XSLT不会那样工作。如果该值是节点集,那么您可以在将变换应用于该值时进行排序。但是,如果您只使用变量值一次,那么您根本不需要变量 - 您也可以直接表达变换。

然后,这是样式表(在XSLT 1.0中)的变体,它产生预期的输出结构:

<video>

您还可以为排序键指定更复杂的表达式,以及多个排序键。在后一种情况下,密钥从最重要到最不重要。例如,如果您的<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> <xsl:template match="/"> <hmtl> <head> <title>New Version!</title> </head> <videos> <!-- iterate over (all) the <pick> elements, in sorted order --> <xsl:for-each select="test/video/sec/pick"> <!-- sort keys must come first --> <xsl:sort select="v" data-type="number" order="descending" /> <xsl:copy-of select="."/> </xsl:for-each> </videos> </hmtl> </xsl:template> </xsl:stylesheet> 元素旨在被解释为编码与<v>元素相同日期的结构化数字字符串,则按它们所代表的日期的降序排序,那么您可以替换它样式表片段代替上面相应的一个:

<mediadate>