XSLT。将特定类型的所有节点移动到一个节点中

XSLT. Move all nodes of specific type into one node

我有一个 XML(folderfile 节点的数量可以变化):

<root>
  <system>3</system>
  <type>0</type>
  <file name="a"/>
  <folder name="aaa">
    <file name="b"/>
    <file name="c"/>
    <folder name="bbb">
      <file name="d"/>
      ...
    </folder>
    <folder name="ccc">
      <file name="e"/>
      ...
    </folder>
    ...
  </folder>
  ...
</root>

应转换为:

<root>
  <system>3</system>
  <type>0</type>
  <folder name="all_files">
    <file name="a"/>
    <file name="b"/>
    <file name="c"/>
    ...
  </folder>
</root>

我需要使用 XSLT 来完成,但我有一个问题,我不知道如何将 file 个节点复制到 (<folder name="all_files">) 个节点中。

可以吗?

一个解决方案遵循 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
  <xsl:template match="/">
    <root>
        <xsl:apply-templates select="//system | //type" mode="copy" />
        <folder name="all_files">
            <xsl:apply-templates select="//file" mode="copy" />
        </folder>
    </root>
  </xsl:template>
  <xsl:template match="@*|node()" mode="copy">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
</xsl:transform>

应用于您的输入 XML,生成以下输出:

<root>
  <system>3</system>
  <type>0</type>
  <folder name="all_files">
    <file>a</file>
    <file>b</file>
    <file>c</file>
    <file>d</file>
    <file>e</file>
  </folder>
</root>

匹配根级别的模板将模板应用于systemtype节点,模式为copy(以防止复制所有节点,模板匹配所有节点和属性) .
然后,包裹在 <folder name="all_files"> 中,相同的模板应用于所有 file 节点。

为此转换保存 Demo