基于属性结尾的XML转换

时间:2013-05-28 13:26:06

标签: xml xslt

我有这个xml代码:

<items>
    <item name="xyz_low" />
    <item name="xyz_hight" />
    <item name="xyz_medium" />
    <item name="abc_medium" />
    <item name="abc_low" />
    <item name="abc_hight" />
</items>

我想得到类似的东西:

<items>
    <item name="xyz_hight" />
    <item name="xyz_medium" />
    <item name="xyz_low" />
    <item name="abc_hight" />
    <item name="abc_medium" />
    <item name="abc_low" />
</items>

排序仅在具有相同属性名称的第一部分(下划线之前的部分)的标记之间发生。订单是高,中,低。

我看ends-with,但这对我来说还不够,因为我不知道第一部分是xyz,abc还是别的。

我不需要对第一部分进行排序:我只想以同样的方式对项目标签组中的后缀进行排序。

是否可以选择不同的方法?

1 个答案:

答案 0 :(得分:2)

要按照这样的固定顺序对项目进行排序,您可以使用这样的技巧:为排序顺序定义变量

<xsl:variable name="sortOrder" select="'|hight|medium|low|'" />

现在您可以使用

进行排序
<xsl:sort select="string-length(substring-before($sortOrder, concat('|', value, '|')))"
          data-type="number" />

您需要的value。如果value为“hight”,则substring-before的长度为0,“medium”的长度为6,等等。

这是一个XSLT 2.0模板,它会做你想要的事情,假设变量定义

<xsl:template match="items">
  <items>
    <xsl:for-each-group select="item" group-adjacent="substring-before(@name, '_')">
      <xsl:perform-sort select="current-group()">
        <xsl:sort select="string-length(substring-before($sortOrder,
                                concat('|', substring-after(@name, '_'), '|')))"
          data-type="number" />
      </xsl:perform-sort>
    </xsl:for-each-group>
  </items>
</xsl:template>

要在XSLT 1.0中做同样的事情,你需要做一个Muenchian分组技巧

<xsl:key name="itemByPrefix" match="item" use="substring-before(@name, '_')" />

然后在模板中

<xsl:template match="items">
  <items>
    <xsl:for-each select="item[generate-id() = generate-id(
                key('itemByPrefix', substring-before(@name, '_'))[1])]">
      <xsl:for-each select="key('itemByPrefix', substring-before(@name, '_'))">
        <xsl:sort select="string-length(substring-before($sortOrder,
                                concat('|', substring-after(@name, '_'), '|')))"
          data-type="number" />
        <xsl:copy-of select="." />
      </xsl:for-each>
    </xsl:for-each>
  </items>
</xsl:template>

(如果源文档中有几个不同的items集合,XSLT 2.0版本仍然有效,在这种情况下,XSLT 1.0版本会变得更加混乱。“