如何使用XSLT对XML的子元素进行排序

Dan*_*ler 7 xml sorting xslt

我有一个输入XML文件,我需要将1:1复制到输出,除了一个包含需要排序的子项的子元素.

<?xml version="1.0"?>
<top>
  <elementA />
  <elementB />
  <contents>
      <contentitem>
          <id>3</id>
          <moretags1 />
          <moretags2 />
      </contentitem>
      <contentitem>
          <id>2</id>
          <moretags1 />
          <moretags2 />
      </contentitem>
      <contentitem>
          <id>1</id>
          <moretags1 />
          <moretags2 />
      </contentitem>
  </contents>
</top>
Run Code Online (Sandbox Code Playgroud)

我想要一个XSL转换,它将"contentitem"元素按顺序排列,按其"id"元素排序.必须逐字复制所有其他标记,包括嵌套标记.我已经尝试过使用xsl:copy,但要么我得到了双重内容,要么结果丢失了.

Dim*_*hev 7

Mark Gravell的解决方案几乎是正确的 - 有一个创建两个嵌套<contents>元素的小问题.所有提供答案的人都要注意:测试你的解决方案!

这是一个正确的解决方案.这种转变:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
<!--                                                --> 
 <xsl:strip-space elements="*"/>
<!--                                                --> 
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
<!--                                                --> 
  <xsl:template match="contents">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="contentitem">
        <xsl:sort select="id" data-type="number"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当应用于最初提供的XML文档时:

<top>
    <elementA />
    <elementB />
    <contents>
        <contentitem>
            <id>3</id>
            <moretags1 />
            <moretags2 />
        </contentitem>
        <contentitem>
            <id>2</id>
            <moretags1 />
            <moretags2 />
        </contentitem>
        <contentitem>
            <id>1</id>
            <moretags1 />
            <moretags2 />
        </contentitem>
    </contents>
</top>
Run Code Online (Sandbox Code Playgroud)

产生想要的,正确的结果:

<top>
   <elementA/>
   <elementB/>
   <contents>
      <contentitem>
         <id>1</id>
         <moretags1/>
         <moretags2/>
      </contentitem>
      <contentitem>
         <id>2</id>
         <moretags1/>
         <moretags2/>
      </contentitem>
      <contentitem>
         <id>3</id>
         <moretags1/>
         <moretags2/>
      </contentitem>
   </contents>
</top>
Run Code Online (Sandbox Code Playgroud)

请注意以下事项:

  1. 使用标识规则无需更改即可复制所有节点.

  2. 如何使用与contents元素匹配的特定模板覆盖标识模板

  3. 使用该<xsl:sort>指令来呈现以特定顺序应用模板的结果,该结果可能与选择用于处理的节点的文档顺序不同.