使用XSLT 2.0在第一个父/祖先的级别上移动子级和后代

时间:2014-01-30 19:15:11

标签: xml xslt xpath

遇到问题需要为此XSLT转换提供解决方案。

来源输入:

<root>
    <title>Title here.</title>
    <div>
        <p>Text here.</p>
        <div>
            <p>Text here.</p>
            <div>
                <p>Text here.</p>
                <div>
                    <p>Text here.</p>
                </div>
            </div>
        </div>
    </div>
</root>

期望的输出:

<root>
    <title>Title here.</title>
    <div>
        <p>Text here.</p>
    </div>
    <div>
        <p>Text here.</p>
    </div>
    <div>
        <p>Text here.</p>
    </div>
    <div>
        <p>Text here.</p>
    </div>
</root>

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

根据Tim C提出的问题(其他命名标签?),您可以简单地使用:

<xsl:template match="root">
  <root>
    <xsl:for-each select="//div/p">
      <div><xsl:copy-of select="." /></div>
    </xsl:for-each>
  </root>
</xsl:template>

答案 1 :(得分:0)

首先要做的是身份模板

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

这将按原样复制元素,因此您只需要为要转换的元素编写模板。在这种情况下,看起来你想要转换具有至少一个元素作为子元素的元素(除了根元素),因此模板匹配将如下所示

<xsl:template match="*/*[*]">

在此范围内,您需要复制元素,但只处理没有其他元素作为子元素的子节点

  <xsl:copy>
     <xsl:apply-templates select="@*|node()[not(self::*[*])]"/>
  </xsl:copy>

最后,在此副本之后,您可以选择带子项的子元素,以便在当前元素之后复制它们

<xsl:apply-templates select="*[*]"/>

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

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

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

应用于XML示例时,输出以下内容

<root>
    <title>Title here.</title>
    <div>
        <p>Text here.</p>
    </div>
    <div>
        <p>Text here.</p>
    </div>
    <div>
        <p>Text here.</p>
    </div>
    <div>
        <p>Text here.</p>
    </div>
</root>

这是一个非常通用的解决方案,可以使用所有标记名称,而不仅仅是DIV标记。