XSLT更改元素顺序

时间:2016-05-25 16:22:17

标签: xslt

说我有以下xml:

<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns="http://someorg.org">
    <name>
    <use value="usual"/>
    <family value="family"/>
    <given value="given"/>
    <suffix value="MSc"/>
  </name>
</Test>

我希望改变顺序,例如在家庭之前给出,以便我们有:

<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns="http://someorg.org">
    <name>
    <use value="usual"/>
    <given value="given"/>
    <family value="family"/>    
    <suffix value="MSc"/>
  </name>
</Test>

我尝试使用xsl:paply.template,但问题是,由于apply-templates将模板应用于所有子节点,它还会输出其命令再次被更改的节点,我不知道如何阻止它从将模板应用到订单已被更改的节点。

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://someorg.org"
xmlns="http://someorg.org"
exclude-result-prefixes="f xsl">

    <xsl:template match="*">
        <xsl:element name="{local-name(.)}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>


    <xsl:template match="@*">
        <xsl:attribute name="{local-name(.)}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="/">

        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match = "f:name">
    <xsl:apply-templates select = "f:given"/>
    <xsl:apply-templates select = "f:family"/>
    <xsl:apply-templates/>          
    </xsl:template>     
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:3)

要更改您需要的顺序apply-templates,即

<xsl:template match = "f:name">
  <xsl:copy>
     <xsl:apply-templates select="f:use"/>
     <xsl:apply-templates select="f:given"/>
     <xsl:apply-templates select="f:family"/>
     <xsl:apply-templates select="f:suffix"/>
  </xsl:copy>          
</xsl:template>    

使用XSLT 2.0更容易编写

<xsl:template match = "f:name">
  <xsl:copy>
     <xsl:apply-templates select="f:use, f:given, f:family, f:suffix"/>
  </xsl:copy>          
</xsl:template>  

答案 1 :(得分:2)

这是一个通用而简短的完整XSLT 1.0解决方案

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="http://someorg.org">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vOrdered" select="'|use|given|family|suffix|'"/>

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

  <xsl:template match="my:name">
    <xsl:copy>
      <xsl:apply-templates select="*">
        <xsl:sort select="substring-before($vOrdered, concat('|',name(),'|'))"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时

<Test xmlns="http://someorg.org">
    <name>
        <use value="usual"/>
        <family value="family"/>
        <given value="given"/>
        <suffix value="MSc"/>
    </name>
</Test>

生成了想要的正确结果

<Test xmlns="http://someorg.org">
   <name>
      <use value="usual"/>
      <given value="given"/>
      <family value="family"/>
      <suffix value="MSc"/>
   </name>
</Test>

请注意

  1. 如果我们想要指定<xsl:apply-templates>元素子元素的新顺序,则只使用一条f:name指令并且不会更改模板的代码。

  2. 元素的排序可以在一个单独的XML文档中指定,该文档可以使用标准函数动态获取,例如document()到当前的XSLT样式表中并用作独立的&#34;配置文件&#34 ;.然后,当需要新的排序时,永远不需要修改转换 - 只需要修改配置文件。