按名称对XML元素排序,并按文本进一步对元素进行排序

时间:2013-03-18 16:31:32

标签: xslt

我想知道如何根据第一个元素名称对XML进行排序,而不是基于少数这些元素的文本。 在基本术语中,如果我在同一级别具有元素'd,e,c,a,b'元素,我希望它们被命名为'a,b,c,d,e'。 另一个要求是在'b,c,d'元素中按文本对a / b / c / d / e的组进行排序。因此,如果一组b,c,d包含'b1,c1,d1',另一组包含'b2,c2,d2',那么首先应该出现'(1)的设置(按字母顺序排列,我不需要数字订购)。 (用sql术语:按b,c,d排序)

我有XML,例如。

<top_tag>
 <next_tag>
  <a_element>valueX</a_element>
  <b_element>valueZ</b_element>
  <d_element>
   <property>on</property>
   <header>hello</header>
   <column_name>columnC</column_name>
   <a_element>valueX</a_element>
   <b_element>valueZ</b_element>
  </d_element>
  <c_element>valueC</c_element>
  <d_element>
   <property>off</property>
   <header>hi</header>
   <column_name>columnA</column_name>
   <a_element>valueX</a_element>
   <b_element>valueZ</b_element>
  </d_element>
 </next_tag>
 <next_tag>
  <a_element>valueA</a_element>
  <b_element>valueB</b_element>
  <d_element>
   <property>on</property>
   <header>hello</header>
   <column_name>columnAAA</column_name>
   <a_element>valueA</a_element>
   <b_element>valueB</b_element>
  </d_element>
  <c_element>valueC</c_element>
  <d_element>
   <property>off</property>
   <header>hi</header>
   <column_name>columnA</column_name>
   <a_element>valueA</a_element>
   <b_element>valueB</b_element>
  </d_element>
 </next_tag>
</top_tag>

我想得到这个:(用'a_element和b_element'排序next_tag,用'a_element,b_element和column_name'排序d_element)

<top_tag>
  <next_tag>
    <a_element>valueA</a_element>
    <b_element>valueB</b_element>
    <c_element>valueC</c_element>
    <d_element>
      <a_element>valueA</a_element>
      <b_element>valueB</b_element>
      <column_name>columnA</column_name>
      <header>hi</header>
      <property>off</property>
    </d_element>
    <d_element>
      <a_element>valueA</a_element>
      <b_element>valueB</b_element>
      <column_name>columnAAA</column_name>
      <header>hello</header>
      <property>on</property>
    </d_element>
  </next_tag>
  <next_tag>
    <a_element>valueX</a_element>
    <b_element>valueZ</b_element>
    <c_element>valueC</c_element>
    <d_element>
      <a_element>valueX</a_element>
      <b_element>valueZ</b_element>
      <column_name>columnA</column_name>
      <header>hi</header>
      <property>off</property>
    </d_element>
    <d_element>
      <a_element>valueX</a_element>
      <b_element>valueZ</b_element>
      <column_name>columnC</column_name>
      <header>hello</header>
      <property>on</property>
    </d_element>
  </next_tag>
</top_tag>

我在这里找到了如何按字母顺序排序元素: XSLT to sort nodes by name?

但是,如果我按元素应用顺序(很可能不正确),则所有元素名称都会被加扰(超出元素名称顺序)。

对于这个处理,可以使用xslt的多次传递来获得最终结果,我没有要求有一个同时执行这两个操作的xsl文件(按元素和按名称排序)

这整个练习就是这样我可以做一个'差异'(或者无法比较)并且能够理解XML的变化。

1 个答案:

答案 0 :(得分:1)

您可以在<xsl:sort>apply-templates

中拥有多个for-each
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes" />

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

  <xsl:template match="top_tag">
    <top_tag>
      <xsl:apply-templates select="next_tag">
        <xsl:sort select="a_element" />
        <xsl:sort select="b_element" />
      </xsl:apply-templates>
    </top_tag>
  </xsl:template>

  <xsl:template match="next_tag">
    <next_tag>
      <xsl:apply-templates select="*">
        <xsl:sort select="name()" />
        <xsl:sort select="a_element" />
        <xsl:sort select="b_element" />
        <xsl:sort select="column_name" />
      </xsl:apply-templates>
    </next_tag>
  </xsl:template>

  <xsl:template match="d_element">
    <d_element>
      <xsl:apply-templates select="*">
        <xsl:sort select="name()" />
      </xsl:apply-templates>
    </d_element>
  </xsl:template>
</xsl:stylesheet>

这里的关键点是select的{​​{1}}表达式应用于被视为排序的节点作为上下文节点,因此sort模板将首先对其子项进行排序按元素名称,然后如果两个元素具有相同的名称,它们将按其各自的next_taga_elementb_element子元素(如果有)的值按顺序排序。