xslt 解析层次结构并复制到新文档中

xslt resolve hierarchy and copy into new document

我有一个这样的 xml 文档:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nodes>
<node id="123">
   <elemref id="1"/>
   <elemref id="2"/>
   <noderef id="222"/>
</node>
<node id="456">
   <elemref id="4">
      <elemref id="2828"/>
   </elemref>
   <elemref id="5"/>
   <noderef id="444"/>
</node>
<node id="222">
   <elemref id="6"/>
   <elemref id="8"/>
   <noderef id="666"/>
</node>
<node id="444">
   <elemref id="11"/>
   <elemref id="22"/>
   <noderef id="888"/>
</node>
</nodes>

预期输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nodes>
<node id="123">
   <elemref id="1"/>
   <elemref id="2"/>
   <subnode id="222">
       <elemref id="6"/>
       <elemref id="8"/>
   <!-- resolve noderef 666 -->
   </subnode>  
</node>
<node id="456">
   <elemref id="4">
      <elemref id="2828"/>
   </elemref>
   <elemref id="5"/>
   <subnode id="444">
       <elemref id="11"/>
       <elemref id="22"/>
       <!-- resolve noderef 888 -->
   </subnode>
</node>
</nodes>

所以基本上我需要解析所有的节点引用。它们所引用的节点在同一个文档中(为简洁起见,此处省略了节点 666 和 888)。我需要一个正确显示节点和 elemrefs 层次结构的文档。一切都可以嵌套任意深度。

因此每个节点可以有未知数量的 elemrefs,每个 elemrefs 可以包含可变数量的 elemrefs 和 noderefs,后者又包含 elemrefs 等等。

如果有任何提示和帮助,我将不胜感激!使用 XSLT 2.0

如果我理解正确的话,使用 keys:

应该很容易做到

XSLT

<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="*"/>

<xsl:key name="node-by-id" match="node" use="@id" />
<xsl:key name="noderef-by-id" match="noderef" use="@id" />

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

<!-- only unreferenced nodes are ancestors -->
<xsl:template match="/nodes">
    <xsl:copy>
        <xsl:apply-templates select="node[not(key('noderef-by-id', @id))]"/>
    </xsl:copy>
</xsl:template>

<!-- resolve references -->
<xsl:template match="noderef">
    <subnode id="{@id}">
       <xsl:apply-templates select="key('node-by-id', @id)/*"/>
   </subnode>  
</xsl:template>

</xsl:stylesheet>

希望您没有任何循环引用。