Xml 如何在xslt中使用xsl:sort?

Xml 如何在xslt中使用xsl:sort?,xml,sorting,xslt,xslt-1.0,Xml,Sorting,Xslt,Xslt 1.0,我有一个包含两个元素的XML文件。My transform通过每个的一个,将这些元素合并为一个元素,并将结果记录为变量variableA的值 我是否可以根据原始数据中元素的值对转换后的内容进行排序 这是我的密码 输入xml <test> <video graph="1" potime="1811"> <sec> <secid>3812907</secid> <

我有一个包含两个
元素的XML文件。My transform通过每个的一个
,将这些元素合并为一个
元素,并将结果记录为变量
variableA
的值

我是否可以根据原始数据中
元素的值对转换后的内容进行排序

这是我的密码

输入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>
我希望
中生成的
元素按其
子元素(从输入文档复制)降序排序,如图所示

以下是我当前的转换:

<?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>

新版本!

可能需要对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>

您当然可以使用
xsl:sort
生成所需的输出。既然你知道这个元素,但仍然问这个问题,我想你试着使用它,但没有得到你想要的结果。考虑到样式表的当前结构,这并不奇怪

关于
xsl:sort
需要了解的最重要的事情之一是它导致排序的原因,即
apply templates
为与其关联的每个
元素选择的输入节点<代码>xsl排序
使输入节点按照它描述的顺序进行处理,上下文的当前节点列表也以这种方式进行排序。这对于您编写的样式表来说是一个问题,因为您要排序的是
元素,而您要迭代的是
元素

此外,不清楚为什么在这里引入变量。我怀疑您误解了可能会在设置变量后对其内容进行排序,但XSLT并不是这样工作的。如果该值是一个节点集,则可以在对该值应用变换时进行排序。但是,如果只使用变量的值一次,那么就根本不需要变量——最好直接表示转换

下面是样式表(XSLT 1.0中)的一个变体,它生成预期的输出结构:

<?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>

新版本!
您还可以为排序键以及多个排序键指定更复杂的表达式。在后一种情况下,键从最重要到最不重要进行解释。例如,如果您的
元素被解释为结构化数字字符串,编码与
元素相同的日期,并按它们所代表的日期降序排序,那么您可以用此样式表片段代替上面相应的片段:

        <xsl:for-each select="test/video/sec/pick">
          <!-- sort keys must come first -->
          <xsl:sort select="substring(v, 5, 4)" data-type="number" order="descending" />
          <xsl:sort select="substring(v, 3, 2)" data-type="number" order="descending" />
          <xsl:sort select="substring(v, 1, 2)" data-type="number" order="descending" />
          <xsl:sort select="substring(v, 9, 4)" data-type="number" order="descending" />
          <xsl:copy-of select="."/>
        </xsl:for-each>


这一点和其他问题一样不清楚。为什么需要变量呢?为什么不简单地对源XML的节点进行排序并将结果直接写入输出?您已经提供了XSLT 2.0样式表,但是您已经标记了[XSLT-1.0]。您实际上打算使用哪个版本的XSLT?@JohnBollinger请不要对问题添加您自己的解释。@michael.hor257k,我们只能对问题进行自己的解释。编辑问题以改进问题完全符合SO的规范,如果OP认为编辑不适当地改变了问题的性质,那么他完全有能力将其回滚或进一步编辑。当然,这也是你的特权,但我不清楚你在这里到底做了什么。你删除了和variableA语法,得到了相同的结果。可能会简化您的代码。虽然这确实会产生类似于OP中所示的输出,但我怀疑这只是巧合。
v
值以
ddmmyyyhhmm
格式清楚地表示日期和时间-我认为很明显,它们需要按年、月、日和时间顺序分别排序(正如我在这个问题的第一次迭代中向OP建议的那样)。现在谁来解释这个问题,@michael.hor257k?但你可能是对的。我已经更新了我的答案来解决这个问题,但我已经清楚地提出了我自己的解释。如果我试图通过编辑问题来强迫每个人接受,那么你的观点是正确的。顺便说一句,你可以将最后两个组合到
子字符串(v,9,4)
        <xsl:for-each select="test/video/sec/pick">
          <!-- sort keys must come first -->
          <xsl:sort select="substring(v, 5, 4)" data-type="number" order="descending" />
          <xsl:sort select="substring(v, 3, 2)" data-type="number" order="descending" />
          <xsl:sort select="substring(v, 1, 2)" data-type="number" order="descending" />
          <xsl:sort select="substring(v, 9, 4)" data-type="number" order="descending" />
          <xsl:copy-of select="."/>
        </xsl:for-each>