使用XSLT以其他格式转换XML

时间:2017-10-31 10:13:02

标签: xml xslt

我是XSLT的新手,我很困惑。我必须解决以下问题。

<root>
<level_1 name="Level 1">
    <level_2 name="Level 2">
        <level_3 name="Level 3">
            <level_4 name="Level 4">
                <level_5 name="Level 5">
                    <level_6 name="level_6 1" />
                    <level_6 name="level_6 2" />
                </level_5>
            </level_4>
        </level_3>
    </level_2>     
</level_1>
</root>

我想以一种上面没有深层嵌套的形式转换这个文件。 所以它必须看起来像:

<root>
<level_1 name="level_1">
    <level_2 name="level_2"/>
    <level_3 name="level_3"/>
    <level_4 name="level_4"/>
    <level_5 name="level_5"/>
    <level_6 name="level_6 1"/>
</level_1>
<level_1 name="level_1">
    <level_2 name="level_2"/>
    <level_3 name="level_3"/>
    <level_4 name="level_4"/>
    <level_5 name="level_5"/>
    <level_6 name="level_6 2"/>
</level_1>
</root>

现在所有级别都嵌套在<level_1>中。此外,在源XML中有两个<level_6>元素。在我的目标XML中,这两个元素位于不同的<level_1>元素中。 我不知道,因为我是XSLT的新手。

请解释。

1 个答案:

答案 0 :(得分:2)

不幸的是,一个示例输入和输出不构成规范。我们不仅要知道样式表应该对这个输入做什么,还要知道它应该如何处理其他输入。例如,对于叶节点不在同一级别的输入应该怎么做。

但是,如果要求扩展每个叶元素(没有子元素的元素)的路径,那么你可以尝试这个(在XSLT 3.0中):

<xsl:template match="root">
  <xsl:variable name="root" select="."/>
  <xsl:copy>
    <xsl:for-each select="//*[not(*)]">
      <xsl:variable name="ancestors" select="ancestor-or-self::* except $root"/>
      <xsl:copy select="head($ancestors)">
         <xsl:copy-of select="@*"/>
         <xsl:for-each select="tail($ancestors)">
           <xsl:copy>
             <xsl:copy-of select="@*"/>
           </xsl:copy>
         </xsl:for-each>
      </xsl:copy>
    </xsl:for-each>
  </xsl:copy>
</xsl:template>