如何使用XSLT置换节点层次结构?

时间:2015-06-02 20:24:32

标签: xslt

首先:我是XSLT的初学者。在一个项目中,我们以更抽象的方式合成树转换。对于概念证明,我试图将域扩展为简单的XSLT

但是,让我们看一个例子,我的XML文档中有几个叶子,就像在这里:

<input>
       <a>
         <b>
           <c>Foo </c>
           <c>Bar </c>
         </b>
       </a>
       <x>
         <y>
           <z>Foobar </z>
         </y>
       </x>
</input>

对于我想做的事情,可以更容易地查看路径。 a/b/c/Fooa/b/c/Bar/x/y/z/Foobar

我想要做的是根据路径中的索引更改层次结构。例如,我想先按顺序排列:第三级,第一级,第二级。对于上述路径:c/a/b/Foo/c/a/b/Bar/z/x/y/Foobar

我的方法看起来像这样:

<xsl:template name="leaf">
  <xsl:copy>
        <!-- copy attributes-->                                   
        <xsl:copy-of select="@*" />                                  
        <!-- take another level-->
        <xsl:copy select="../"/>
    </xsl:copy>                     
</xsl:template>  

但显然当我在<copy>时,我无法使用&#34; ../"再得到父元素。我正在寻找任何解决方案来进行这种转换。要么使用完全不同的(我对XSLT的看法非常狭隘),要么通过调整我的方法。

期望的输出:

<output>
    <c>
        <a>
            <b>Bar</b>
        </a>
    </c>
    <c>
        <a>
            <b>Foo</b>
        </a>
    </c>
    <z>
        <x>
            <y>Foobar</y>
        <x>
    <z>    
</output>

其他信息

  • 输入XML总是深度为3(没有计数)

第二个例子

<input>
    <one>
        <two>
            <three>
                bla
            </three>
        </two>
        <two>
            <three>
                blub
            </three>
        </two>
    </one>
</input>

<output>
    <three>
        <one>
            <second>bla</second>
        </one>
        <one>
            <second>blub</second>
        </one>
    </three>
</output>

我还不确定我是否明确了要实现的转型。也许这个想法会有所帮助:想象一下,我完全分解了输入XML:对于每个叶子,考虑叶子本身和叶子的路径,然后根据规则(第三,第一,第二)转换路径。

1 个答案:

答案 0 :(得分:0)

这不是一个非常优雅的方法,但它有效:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/input">
    <output>
        <xsl:apply-templates select="*/*/*/text()"/>
    </output>
</xsl:template>

<xsl:template match="text()">
    <xsl:element name="{name(ancestor::*[1])}">
        <xsl:element name="{name(ancestor::*[3])}">
            <xsl:element name="{name(ancestor::*[2])}">
                <xsl:copy-of select="."/>
            </xsl:element>
        </xsl:element>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>