XSLT xsl:排序失败,数字大,data-type ="number"

Eri*_*ric 1 xslt

我讨厌甚至问这个,因为有很多关于xsl:sort功能的例子,但是我已经跟着他们而且仍然,莫名其妙地,卡住了.

我在for-each中有一种,似乎是要求.然后,我希望获取所有已排序的数据并应用模板.

这是一个示例XML.我有一组日志元素和结果元素,在不同的路径上,我需要根据数字时间戳值一起排序.在这个例子中,除了最后一个datatimestamp值大于三个结果元素的元素之外,一切都已经自然地排序了,这意味着它应该出现在输出的最后.如上所述,输出将按照它们在输入XML中出现的顺序显示所有日志元素,后跟所有结果元素.

<output>
  <logs>
    <log logtext="Username = " loglevel="DEBUG" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428014" />
    <log logtext="Password = " loglevel="DEBUG" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428027" />
    <log logtext="ServerURI = " loglevel="DEBUG" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428042" />
    <log logtext="TRACE TEST" loglevel="TRACE" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428084" />
    <log logtext="DEBUG TEST" loglevel="DEBUG" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428096" />
    <log logtext="INFO TEST" loglevel="INFO" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428109" />
    <log logtext="WARNING TEST" loglevel="WARN" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428120" />
    <log logtext="ERROR TEST" loglevel="ERROR" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428133" />
    <log logtext="Post-Result INFO Test" loglevel="INFO" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428353" />
  </logs>
  <results>
    <result name="Passed Test" resultformat="TEXT" resulttype="PASS" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428352" />
    <result name="Failed Test" resultformat="TEXT" resulttype="FAIL" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428352" />
    <result name="Running Processes" resultformat="TABLE" resulttype="NONE" timestamp="1/23/2012 5:04:28 PM" numerictimestamp="20120123170428352">
    </result>
  </results>
</output>
Run Code Online (Sandbox Code Playgroud)

以下是XSL的相关部分:

<xsl:template match="/">       
    <html>
       <body>                
        <xsl:for-each select="//logs/log | //results/result">
          <xsl:sort data-type="number" select="@numerictimestamp"/>
          <xsl:apply-templates select="self::node()" />
        </xsl:for-each>
      </body>
</html>
 </xsl:template>

  <xsl:template match="log">
    .... handle formatting of the log elements
  </xsl:template>

  <xsl:template match="result">
    .... handle formatting of the result elements
  </xsl:template>
Run Code Online (Sandbox Code Playgroud)

我想这是一个范围问题,排序只适用于for-each中的单个项目,但我不知道要改变什么来解决它并获得相同的结果.除了排序之外,这个XSL给了我我想要的输出.

EDIT1:

更新问题以包括修改的工作代码,其中包含以下答案和评论 由于要排序的数字太大,排序失败了.它们的时间戳值包括毫秒,具体来说是精确的,因此具有讽刺意味的是,精确度是问题的原因.也就是说,即使用较短的数字将排序放在for-each中,实际上也不会排序多个项目.

大多数使用xsl:sort的例子都是在for-each中做的.我不知道你可以将它包含在apply-templates中.

以下修改正常工作:(请注意,为了清楚起见,我明确指定数据类型为文本,我意识到它是默认值)

  <xsl:apply-templates select="//logs/log | //results/result">       
    <!--The data-type value for the sort MUST be text, due to rounding errors introduced
    attempting to sort the numerictimestamp-->
    <xsl:sort data-type="text" select="@numerictimestamp"/>          
  </xsl:apply-templates>
Run Code Online (Sandbox Code Playgroud)

我能够保持XSL的其余部分不变.

Kev*_*van 5

这样做你想要的吗?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
    <xsl:template match="/">
        <output>
            <xsl:apply-templates select="//log | //result">
                <xsl:sort select="@numerictimestamp"/>
            </xsl:apply-templates>
        </output>
    </xsl:template>

    <xsl:template match="log | result">
        <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

我认为你是正确的,因为for-each正在将范围缩小到当前项目

另一件事是将numerictimestamp属性转换为数字导致舍入.

如果我这样做:

<xsl:template match="log | result">
    <entry>
    <number><xsl:value-of select="number(@numerictimestamp)"/></number>
    <string><xsl:value-of select="@numerictimestamp"/></string>
    </entry>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

我看到了这个:

<entry>
    <number>20120123170428132</number>
    <string>20120123170428133</string>
</entry>
<entry>
    <number>20120123170428352</number>
    <string>20120123170428353</string>
</entry>
<entry>
    <number>20120123170428352</number>
    <string>20120123170428352</string>
</entry>
Run Code Online (Sandbox Code Playgroud)

据我所知,XSLT编号数据类型符合IEEE 754,维基百科告诉我,双精度精确到15.95位数.你的号码是17位数