使用xslt将compact xml表示扩展为更详细的表示

时间:2016-02-06 05:35:39

标签: xslt xslt-2.0

我试图学习xslt作为一种爱好,我感兴趣的一个用例是将某些组件的定义扩展到它们的完整形式。一个例子应该澄清我的意思。例如如果我的输入xml看起来像:

<universe>
    <galaxies>
         <galaxy name="milky way">
             <system name="solar system"/>
         </galaxy>
         <galaxy name="lactose free">
             <system name="windmill system"/>
         </galaxy>
        <galaxy name="parallelish solar system">
            <system name="the earth system"/>
        </galaxy>
    </galaxies>
    <systems>
        <system name="solar system">
            <planet name="pluto"/>
            <system name="the earth system"/>
            <planet name="mercury"/>
        </system>
        <system name="windmill system">
            <planet name="windy"/>
        </system>
        <system name="the earth system">
            <planet name="earth"/>
            <satellite name="moon"/>
        </system>
    </systems>
</universe>

我的输出xml将使这些系统定义在递归的星系定义中扩展(例如太阳系中的地球系统)并且在每个地方定义发生(例如地球系统发生在两个不同的系统中)。系统部分将被删除:

<universe>
    <galaxies>
        <galaxy name="milky way">
            <system name="solar system">
                <planet name="pluto"/>
                <system name="the earth system">
                    <planet name="earth"/>
                    <satellite name="moon"/>
                </system>
                <planet name="mercury"/>
            </system>
        </galaxy>
        <galaxy name="lactose free">
            <system name="windmill system">
                <planet name="windy"/>
            </system>
        </galaxy>
        <galaxy name="parallelish solar system">
            <system name="the earth system">
                <planet name="earth"/>
                <satellite name="moon"/>
            </system>
        </galaxy>
    </galaxies>
</universe>

我对xslt非常陌生,到目前为止,我所遵循的思路一直是以某种方式将这些组件块定义为变量,并在适当的时候插入它们(第二个?通过。然而,正如我在谷歌上搜索并试着找一些例子一样,我还没有成功。我想知道这是否完全可能(我希望如此),以及我需要用什么概念来实现这一目标。示例摘要非常有用。

谢谢!

1 个答案:

答案 0 :(得分:0)

XSLT有一个非常有用的keys机制来解决交叉引用。为了演示它是如何工作的,我首先修改了您的XML示例以避免循环引用:

<强> XML

<universe>
    <galaxies>
         <galaxy name="milky way">
             <system-ref name="solar system"/>
         </galaxy>
         <galaxy name="lactose free">
             <system-ref name="windmill system"/>
         </galaxy>
        <galaxy name="parallelish solar system">
            <system-ref name="the earth system"/>
        </galaxy>
    </galaxies>
    <systems>
        <system name="solar system">
            <planet name="pluto"/>
            <system-ref name="the earth system"/>
            <planet name="mercury"/>
        </system>
        <system name="windmill system">
            <planet name="windy"/>
        </system>
        <system name="the earth system">
            <planet name="earth"/>
            <satellite name="moon"/>
        </system>
    </systems>
</universe>

<强> XSLT

<xsl:stylesheet version="1.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="system-by-name" match="system" use="@name" />

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

<xsl:template match="system-ref">
    <xsl:apply-templates select="key('system-by-name', @name)"/>
</xsl:template>

<xsl:template match="systems"/>

</xsl:stylesheet>

<强>结果

<?xml version="1.0" encoding="UTF-8"?>
<universe>
   <galaxies>
      <galaxy name="milky way">
         <system name="solar system">
            <planet name="pluto"/>
            <system name="the earth system">
               <planet name="earth"/>
               <satellite name="moon"/>
            </system>
            <planet name="mercury"/>
         </system>
      </galaxy>
      <galaxy name="lactose free">
         <system name="windmill system">
            <planet name="windy"/>
         </system>
      </galaxy>
      <galaxy name="parallelish solar system">
         <system name="the earth system">
            <planet name="earth"/>
            <satellite name="moon"/>
         </system>
      </galaxy>
   </galaxies>
</universe>