XSLT - 将现有节点放在不同的位置

XSLT - place existing nodes in different position

我有 xml 如下,

<doc>
  <section>
    <p note="edit"></p>
    <p note="foot"></p>
    <p note="front"></p>
    <c>content</c>
  </section>
  <section>
  .......
  </section>
</doc>

我需要的是摆脱 <p> 具有属性 edit 或 foot 的节点,并将它们添加到 <section> 节点的末尾。

所以输出应该是

  <doc>
      <section>
        <p note="front"></p>
        <c>content</c>
      </section>   
      <p note="edit"></p>
      <p note="foot"></p>          

      <section>
      .......
      </section>
   </doc>

我可以通过简单地使用如下所示的空模板来删除这些节点,

<xsl:template match="p[@note='edit']"/>
<xsl:template match="p[@note='foot']"/>

但是我无法使用任何方法将那些删除的节点放置在 <section> 节点的末尾。

有什么建议吗?

提前致谢

在您的 XSLT 中某处有

元素的输出,您在内部使用 (和脚)作为空模板以避免插入这些(我猜测)。
元素之后,您可以使用元素

<xsl:template match="/doc/section/p[@note='edit']|/doc/section/p[@note='foot']">
  <xsl:copy-of select="."/> 
</xsl:template>

用于在此处插入这些内容。

你可以这样试试:

<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="section">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
    <xsl:copy-of select="p[@note='edit' or @note='foot']"/>
  </xsl:template>

  <xsl:template match="p[@note='edit' or @note='foot']"/>
</xsl:stylesheet>

简要说明:

  • <xsl:template match="node()|@*">... :标识模板。我假设您对此很熟悉。
  • <xsl:template match="section">... : 复制 '<p> 属性为 edit 或 foot' 的节点到当前 <section>, 居住.
  • <xsl:template match="p[@note='edit' or @note='foot']"/> : 用于从原始位置删除具有属性 edit 或 foot' 的 '<p> 节点的空模板。

对于这种情况,我建议在与该部分匹配的模板中使用 xsl:choose。 此模板创建部分元素并对节点重新排序。

   <xsl:template match="section">
    <xsl:choose>
        <xsl:when test="p[@note= 'front']">
            <section>
                <xsl:apply-templates select="p[@note= 'front'] | c"/>
            </section>
            <xsl:apply-templates select="p[@note != 'front']"/>
        </xsl:when>
        <xsl:otherwise>
            <section>
                <xsl:apply-templates/>
            </section>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

演示:http://xsltransform.net/jyH9rNa/3

或者简单地说:

XSLT 2.0

<xsl:stylesheet version="2.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="*"/>

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

<xsl:template match="section">
    <xsl:variable name="footnotes" select="p[@note='edit' or @note='foot']" />
    <xsl:copy>
        <xsl:apply-templates select="@*|node() except $footnotes"/>
    </xsl:copy>
    <xsl:apply-templates select="$footnotes"/>
</xsl:template>

</xsl:stylesheet>