2017-04-24 42 views
0

我有一个包含两个<video>元素的XML文件。我的变换通过for-each将这些元素合并为一个<videos>元素,将结果记录为变量variableA的值。如何在xslt中使用xsl:sort?

我可以根据原始数据中<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我想我的变量variableA。有使用这个值我想我的排序变量v标签值

预计产量

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

我想要的<videos>内所得<pick>元件以在通过<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> 
+0

这就像不清[你以前的尝试(http://stackoverflow.com/questions/43592138/how-to-assign-value-in-variable-using-xslt)。为什么你需要变量?为什么不简单地对源XML的节点进行排序并将结果直接写入输出? –

+0

您已经提供了XSLT 2.0样式表,但已标记了[xslt-1.0]。你真的打算使用哪个版本的XSLT? –

+0

@JohnBollinger请不要在问题中加上你自己的解释。 –

回答

0

可能有点tweek到的for-each和排序会有所帮助。让我们知道。

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

您可以移除和变量A的语法并获得相同的结果。可以简化你的代码。 – Bluewood66

0

你当然可以用xsl:sort来产生你想要的输出。因为你知道这个元素,但仍然会问这个问题,我想你会尝试使用它,但没有得到你想要的结果。考虑到样式表的当前结构,这并不令人惊讶。

其中一个最重要的事情要了解有关xsl:sort什么原因进行排序,这是与它相关联的apply-templatesfor-each元素选择的输入节点。 xsl-sort会导致输入节点按其描述的顺序进行处理,同时上下文的当前节点列表也以此方式排序。这对于样式表是一个问题,因为它是您要排序的<pick>元素,但是您要迭代的元素是<video>

此外,目前还不清楚为什么你在这里引入一个变量。我怀疑你有错误的理解,你可能会在变量设置后对变量的内容进行排序,但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> 

您也可以指定排序键更复杂的表达式,以及多个排序键。在后一种情况下,按键从最重要到最不重要。例如,如果你的<v>元素旨在解释为编码相同的日期作为<mediadate>元素,按降序他们所代表的日期的顺序进行排序结构化数字串,那么你可能会在地方相应的一个替代这个样式表片段以上:

 <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> 
+0

虽然这确实会产生类似于OP中显示的输出,但我怀疑这不过是巧合。 'v'值清楚地表示'DDMMYYYYHHMM'格式的日期和时间 - 我认为这很明显,他们需要按年份,月份,日期和时间分别进行排序(按照我已经建议的OP这个问题的第一次迭代)。 –

+0

谁将他们的解释带给现在的问题,@ michael.hor257k?但你可能是对的。我已经更新了我的答案来解决这个问题。 –

+0

但我清楚地表明这是我自己的解释。如果我试图通过编辑问题来强迫每个人,那么你会有一个有效的观点。 –