XSL排序特定值最后

时间:2018-07-30 10:54:46

标签: xslt xslt-1.0

是否可以按以下方式对节点进行排序:

示例XML

<record>
   <id>0</id>
   <sku>0</sku>
   <name>Title</name>
   <prop>456</prop>
   <number>99</number>
</record>

如果我应用此模板

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
     <xsl:template match="record/*">
     <xsl:param select="." name="value"/>
        <div>
           <xsl:value-of select="concat(local-name(), ' - ', $value)"/>
         </div>
     </xsl:template>
</xsl:stylesheet>

输出:

<div>id - 0</div>
<div>sku - 0</div>
<div>name - Title</div>
<div>prop - 456</div>
<div>number - 99</div>

但是,我希望最后输出所有0个值,如下所示:

<div>name - Title</div>
<div>prop - 456</div>
<div>number - 99</div>
<div>id - 0</div>
<div>sku - 0</div>

是否可以通过对<xsl:apply-templates/>进行排序来实现?

2 个答案:

答案 0 :(得分:1)

使用XSLT-1.0可以轻松实现这一目标。只需在xsl:apply-templates上使用谓词即可检查内容是否为零:

 <xsl:template match="record/*">
    <div>
       <xsl:value-of select="concat(local-name(), ' - ', .)"/>
     </div>
 </xsl:template>

 <xsl:template match="/record">
    <xsl:apply-templates select="*[normalize-space(.) != '0']" />
    <xsl:apply-templates select="*[normalize-space(.)  = '0']" />
 </xsl:template>

这不会对输出进行排序,而是按照您希望的方式对其进行分组。 xsl:param是不必要的。

答案 1 :(得分:0)

据我所见,您的问题根本不是任何问题。 您甚至没有写出您提到的特定值 它的标题。它是record子元素的任意序列

尝试以下脚本,只需执行以下操作即可:

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

  <xsl:template match="record">
    <xsl:copy>
      <xsl:apply-templates select="name, prop, number, id, sku"/>  
    </xsl:copy>
  </xsl:template>

  <xsl:template match="record/*">
    <div><xsl:value-of select="concat(local-name(), ' - ', .)"/></div>
  </xsl:template>

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

我使用XSLT 2.0,因为最初您没有指定XSLT版本。 您可以继续使用2.0版吗?如您所见,它允许编写 一个精致的解决方案(在1.0版中是不可能的)。

我还更改了与record/*匹配的模板。你其实不 需要任何 param 。使用.-当前值 元素。

编辑

另一种可能性是您希望进行以下排序:

  • 首先,具有非数字值的元素(在您的情况下,仅为name), 也许没有任何帮助。
  • 然后使用数字值的元素,按此值的降序排序。

在这种情况下,请将匹配record的模板更改为 以下:

<xsl:template match="record">
  <xsl:copy>
    <xsl:apply-templates select="*[not(. castable as xs:integer)]"/>  
    <xsl:apply-templates select="*[. castable as xs:integer]">
      <xsl:sort select="." order="descending" data-type="number"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

并添加:

xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"

transform标签。

但是我仍然看不到任何东西,可以称为特定值