0
votes

I'm new in xml and I'am trying to understand a example of xslt

the 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) the first 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) the second 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>

and the results are: 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>

can anybody tells me how it works especially the second xsl how it gives the result with three T1. Thanks a lot for your help :)

1

1 Answers

0
votes

With regard to your first stylesheet:

The second template:

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

does not match anything in the given XML document, because there's no t element that is a child of the / root node. So all your stylesheet does is copy the given XML document as is, courtesy of the first template.

With regard to your second stylesheet:

To better understand what happens here, I would suggest you change the second template to:

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

The result of this will be:

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

What does this tell us?

You can see that the second template was instantiated twice (which is as expected, since there are exactly two t elements with a @ref attribute).

Please make a note of which nodes are called by the key.

Now, if change the template once again to:

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

the result will be:

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

As you can see, the second instance of the template caused another, third instantiation of the same template. This is because the second instance applied templates to the:

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

node, which has a @ref attribute itself, and therefore is matched by the same template. However, this time the key calls the:

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

node, which does not have a @ref attribute, and therefore will be copied by the first template.