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

时间:2015-04-27 14:53:08

标签: xml xslt xslt-2.0

我有一个像这样的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>

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

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

我非常感谢任何提示和帮助!使用XSLT 2.0

1 个答案:

答案 0 :(得分:5)

如果我理解正确,使用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>

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