xsl:key和xsl:apply-templates

时间:2015-06-29 20:26:59

标签: xml xslt

我是xml的新手,我试图理解xslt

的一个例子

xml

<?xml version="1.0" encoding="utf-8"?>
<ts>
    <t id="t1">T1</t>
    <t id="t2" ref="t1">T2</t>
    <t id="t3" ref="t2">T3</t>
</ts>

1)第一个xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="key" match="t" use="@id"/>

    <xsl:template match="/|*|text()">
        <xsl:copy>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/t[@ref]">
        <xsl:copy-of select="key('key',@ref)"/>
    </xsl:template>
</xsl:stylesheet>

2)第二个xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="key" match="t" use="@id"/>
    <xsl:template match="/|*|text()">
        <xsl:copy>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="t[@ref]">
        <xsl:apply-templates select="key('key',@ref)"/>
    </xsl:template>
</xsl:stylesheet>

结果如下: 1)

<?xml version="1.0"?>
<ts>
    <t>T1</t>
    <t id="t1">T1</t>
    <t id="t2" ref="t1">T2</t>
</ts>

2)

<?xml version="1.0"?>
<ts>
    <t>T1</t>
    <t>T1</t>
    <t>T1</t>
</ts>

任何人都可以告诉我它是如何工作的,特别是第二个xsl如何给出三个T1的结果。 非常感谢你的帮助:)

1 个答案:

答案 0 :(得分:0)

关于您的第一个样式表:

第二个模板:

<xsl:template match="/t[@ref]">
    <xsl:copy-of select="key('key',@ref)"/>
</xsl:template>

与给定XML文档中的任何内容都不匹配,因为没有t元素是/根节点的子元素。所以你的样式表所做的就是按照第一个模板的原样复制给定的XML文档。

关于您的第二个样式表:

为了更好地理解这里发生的事情,我建议你将第二个模板更改为:

<xsl:template match="t[@ref]">
    <instance>
        <xsl:copy-of select="key('key',@ref)"/>
    </instance>
</xsl:template>

结果将是:

<ts>
  <t>T1</t>
  <instance>
    <t id="t1">T1</t>
  </instance>
  <instance>
    <t id="t2" ref="t1">T2</t>
  </instance>
</ts>

这告诉我们什么?

您可以看到第二个模板已实例化两次(这是预期的,因为恰好有两个t元素具有@ref属性。

请记下密钥调用的节点。

现在,如果再次将模板更改为:

<xsl:template match="t[@ref]">
    <instance>
        <xsl:apply-templates select="key('key',@ref)"/>
    </instance>
</xsl:template>

结果将是:

<ts>
  <t>T1</t>
  <instance>
    <t>T1</t>
  </instance>
  <instance>
    <instance>
      <t>T1</t>
    </instance>
  </instance>
</ts>

如您所见,模板的第二个实例导致了同一模板的另一个第三个实例化。这是因为第二个实例将模板应用于:

<t id="t2" ref="t1">T2</t>

节点,其本身具有@ref属性,因此由相同的模板匹配。但是,这次键调用:

<t id="t1">T1</t>

节点,具有@ref属性,因此将被第一个模板复制。