xml - XSLT:排序路径跟踪

标签 xml xslt

我有以下输入:

<articles>
  <item name="B">
    <item name="Bb">
      <item name="Bbb"/>
      <item name="Abb"/>
    </item>
    <item name="Ab">
      <item name="Bab"/>
      <item name="Aab"/>
    </item>
  </item>
  <item name="A">
    <item name="Ba">
      <item name="Bba"/>
      <item name="Aba"/>
    </item>
    <item name="Aa">
      <item name="Baa"/>
      <item name="Aaa"/>
    </item>
  </item>
  <item name="D"/>
  <item name="C">
    <item name="Ac"/>
  </item>
</articles>

并且需要以下输出:

A-Aa-Aaa
A-Aa-Baa
A-Ba-Aba
A-Ba-BBa
B-Ab-Aab
B-Ab-Bab
B-Bb-Abb
B-Bb-Bbb
C-Ac
D

也就是说,每条路径都应明确并在每个级别上进行排序。我有以下 XSLT,它生成路径,但我无法弄清楚除第一级之外的排序。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="articles">
    <xsl:apply-templates select="//item[not(item)]">
      <xsl:sort select="ancestor-or-self::item[parent::articles]/@name"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="item">
    <xsl:for-each select="ancestor-or-self::item">
      <xsl:value-of select="@name"/>
      <xsl:choose>
        <xsl:when test="not(item)">
          <xsl:text>&#xA;</xsl:text>
        </xsl:when>
        <xsl:otherwise>-</xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

恐怕我目前的做法是一条死胡同。有想法吗?

最佳答案

请注意,XSLT 2.0 解决方案(第二部分)更短、更简单


我。这是一个简单的 2 遍解决方案:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
    <xsl:apply-templates/>
  </xsl:variable>

  <xsl:for-each select="ext:node-set($vrtfPass1)/*">
   <xsl:sort/>
   <xsl:value-of select="concat(., '&#xA;')"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="item[not(item)]">
     <x>
      <xsl:for-each select="ancestor-or-self::item">
       <xsl:if test="not(position() = 1)">-</xsl:if>
       <xsl:value-of select="@name"/>
      </xsl:for-each>
     </x>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<articles>
  <item name="B">
    <item name="Bb">
      <item name="Bbb"/>
      <item name="Abb"/>
    </item>
    <item name="Ab">
      <item name="Bab"/>
      <item name="Aab"/>
    </item>
  </item>
  <item name="A">
    <item name="Ba">
      <item name="Bba"/>
      <item name="Aba"/>
    </item>
    <item name="Aa">
      <item name="Baa"/>
      <item name="Aaa"/>
    </item>
  </item>
  <item name="D"/>
  <item name="C">
    <item name="Ac"/>
  </item>
</articles>

产生了想要的正确结果:

A-Aa-Aaa
A-Aa-Baa
A-Ba-Aba
A-Ba-Bba
B-Ab-Aab
B-Ab-Bab
B-Bb-Abb
B-Bb-Bbb
C-Ac
D

请注意:这是一个通用解决方案,可以正确处理 item 元素的任何嵌套。

说明:

  1. 我们执行两遍转换。

  2. 第一遍的结果是:

    <x xmlns:ext="http://exslt.org/common">B-Bb-Bbb</x>
    <x xmlns:ext="http://exslt.org/common">B-Bb-Abb</x>
    <x xmlns:ext="http://exslt.org/common">B-Ab-Bab</x>
    <x xmlns:ext="http://exslt.org/common">B-Ab-Aab</x>
    <x xmlns:ext="http://exslt.org/common">A-Ba-Bba</x>
    <x xmlns:ext="http://exslt.org/common">A-Ba-Aba</x>
    <x xmlns:ext="http://exslt.org/common">A-Aa-Baa</x>
    <x xmlns:ext="http://exslt.org/common">A-Aa-Aaa</x>
    <x xmlns:ext="http://exslt.org/common">D</x>
    <x xmlns:ext="http://exslt.org/common">C-Ac</x>
    
  3. 第一遍的处理使用仅匹配 leaf item 元素的单个模板。对于每个叶 item 元素,其完整的、破折号分隔的路径将作为名为 x 的元素的内容输出。

  4. 第二遍只是对第一遍的结果进行排序。


二. XSLT 2.0 解决方案:

<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>

 <xsl:template match="/">
     <xsl:for-each-group select="//item[not(item)]"
     group-by="string-join(ancestor-or-self::item/@name, '-')">
      <xsl:sort select="current-grouping-key()"/>
      <xsl:sequence select="current-grouping-key(), '&#xA;'"/>
     </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

关于xml - XSLT:排序路径跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12090372/

相关文章:

html - XSLT:将分组的 html 元素移动到节级别

r - 无法从维基百科中抓取表格

java - 如何使用 XPath 的结果创建 xml 文档

android - 可以在Android Action Bar中通过xml设置ActionViewClass的属性吗?

java - 使用 xlts 进行 xml 转换,按字母顺序排列

xslt - XSLT:是否应用带有条件参数的模板?

c++ - 如何在 C++ 中解析 XML 字符串中的数据?

html - 如何在 XPath 中使用变量?

c# - 如何在 C# 中将 xsl 转换应用于单个 XmlNode 的示例

java - XSLT 使用 concat 或多个 value-of 元素来连接变量?