[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: key() now has 3 arguments ... right

Subject: Re: key() now has 3 arguments ... right
From: ihe onwuka <ihe.onwuka@xxxxxxxxxxxxxx>
Date: Thu, 26 Apr 2012 10:41:32 +0100
Re:  key() now has 3 arguments ... right
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:stylesheet
   xmlns:ren="renames"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   exclude-result-prefixes="ren"
   version="2.0">

<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:variable>

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

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

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

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

</xsl:stylesheet>

Try it with

<people>
   <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"/>
</people

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:next-match/>
</xsl:template>

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

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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.