[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] key() now has 3 arguments ... right

Subject: Re: [xsl] key() now has 3 arguments ... right
From: ihe onwuka <ihe.onwuka@xxxxxxxxxxxxxx>
Date: Thu, 26 Apr 2012 10:41:32 +0100

On Thu, Apr 26, 2012 at 9:32 AM, David Carlisle <davidc@xxxxxxxxx> wrote:
> On 26/04/2012 05:38, ihe onwuka wrote:
>> although I get that there is some difference,
>> given the working example I cannot perceive that it matters.
> I'm not sure what I can do to make it clearer but (except for very special
> types of key definition) there is essentially no similarity between the two
> match expressions and they match completely dofferent elements.
> I'll stick to the 2 argument form as then it is legal and we don't have to
> guess what it means, and the same differences apply there.
> given
> <xsl:key name="k" match="abc" use="@zzz"/>
> match="key('k','123')"
> This matches those nodes (which will be abc elements with attribute zzz =
> 123) returned by the key.
> match="*[key('k','123')]"
> This matches every element in the document if any element is returned by the
> key '123'. Note this is completely different from the behaviour of the first
> match. So it matches <hello/> if the document has an element <abc
> zzz="123"/> and does not match anything otherwise.

I already got that bit. If we were using a tool that highlighted the
matched components of an XPath expression, the first case would only
highlight abc elements with @zzz='123' whereas the second case would
highlight every element in the document if there was an abc element
with @zzz='123'.

Perhaps if I step through the working example I can clarify my question.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="mapNames" match="ren:*/@to" use="../@from"/>

<xsl:variable name="renames">
  <ren:element from="person" to="individual"/>
  <ren:attribute from="firstname" to="christianname"/>
  <ren:attribute from="lastname" to="surname"/>

<xsl:template match="*[key('mapNames',name(),$renames)]">
   <xsl:element name="{key('mapNames',name(),$renames)}">

<xsl:template match="*[not(key('mapNames',name(),$renames))] | @*">
   <xsl:element name="{name()}">

<xsl:template match="*">
    <xsl:apply-templates select="@*"/>

<xsl:template match="@*[key('mapNames',name(),$renames)]">
   <xsl:attribute name="{key('mapNames',name(),$renames)}">


Try it with

   <person firstname="Sal" lastname="Mangano" age="38" height="5.75"/>
   <person firstname="Mike" lastname="Palmieri" age="28" height="5.10"/>
   <person firstname="Vito" lastname="Palmieri" age="38" height="6.0"/>
   <person firstname="Vinny" lastname="Mari" age="37" height="5.8"/>

So the people element will match the 2nd template, which will shallow
copy the people element to the result tree.

The next-match will look locate the third template which
apply-templates to any people attributes (there are none) and
next-matches again, which will invoke the built-in rule to
apply-templates to peoples children.

So far so good.

Next it will process the first person element.

This will get caught by the 1st rule because there is a @from
attribute whose value is the same as the name() of the current node
(which is the person element).

The fact that the template rule matches every element is immaterial,
since my goal of having an element that I have specified should be
renamed (i.e the person element) is about to be achieved.

Looking more closely at 1st template rule there may be an issue
because the AVT of the xsl:element name attribute returns actually
nodeset but that is a separate consideration.

To take another example that I think is conceptually equivalent,
suppose I want to do some additional processing for elements that have
an acme attribute.

So I can process <widget acme="123">.....</widget> with

<xsl:template match = "*[@acme]">
     do something

<xsl:template match="widget">
     process widget

why should I be concerned that "*[@acme]" is matching every element in
the document, if (as I believe) my widget elements are being processed
as intended.

Current Thread