xsl-list
[Top] [All Lists]

Re: [xsl] priority of key patterns

2012-11-14 04:00:54
On Wed, Nov 14, 2012 at 8:48 AM, Michael Kay <mike(_at_)saxonica(_dot_)com> 
wrote:


   <xsl:template match="key('privateData','private')" priority="-0.1">
     <private oldName="{local-name()}">
       <xsl:apply-templates select="node()|@*"/>
     </private>
   </xsl:template>

   <xsl:template match="*|PayloadFile">
    <xsl:element name="{local-name()}">
       <xsl:apply-templates select="node()|@*"/>
    </xsl:element>

Your second template rule is rather peculiar, because the first alternative
(*) embraces the second (Payloadfile); except that they have different
priorities, so this is almost equivalent to writing a match="*" template
with priority -0.5, and a match=Payloadfile template with priority 0. Unless
there's another template rule with intervening priority, the second half of
the union is pointless.


No it's not pointless - see explanation below.


Incidentally, I very rarely see key() used in patterns. I'd be interested to
know the use case. In XSLT 3.0 we're allowing a variable reference as a
pattern, so you can do for example


Here's the full stylesheet.

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns="http://www.xxxxx.com";
    version="2.0">
  <xsl:import href="identity.xsl"/>
  <xsl:output indent="yes"/>
  <xsl:key name="privateData" match="*[@MetadataAccess]" use="@MetadataAccess"/>

  <xsl:template match="TMFFile">
   <xsl:element name="{local-name()}">  
    <publicData>
      <xsl:apply-templates select="key('privateData','public')"/>
    </publicData>       
    <privateData>       
      <xsl:apply-templates select="key('privateData','private')"/>
    </privateData>
   </xsl:element>
  </xsl:template>

  <xsl:template match="key('privateData','private')" priority="-0.1">
    <private oldName="{local-name()}">
      <xsl:apply-templates select="node()|@*"/>
    </private>          
  </xsl:template>

  <xsl:template match="*|PayloadFile">
   <xsl:element name="{local-name()}">  
      <xsl:apply-templates select="node()|@*"/>
   </xsl:element>
  </xsl:template>

</xsl:stylesheet>

My instance is an iteration of heterogenous elements that have a
metadataAccess attribute that classifies the element as either public
or private.

I want to rename all the private elements (except for PayloadFile) and
copy the public elements unchanged. Additionally I want to congregate
the public elements in a publicData wrapper and private elements in a
privateData wrapper.

I have used the key to get at all the private elements in preference to
<private>
  <xsl:apply-templates select="//*[@MetadataAccess='private']
</private>

but am probably not buying much by doing so.

I agree that I could use

  <xsl:template match="*[@MetadataAccess='private']" priority="-0.1">
instead of the key in the match pattern.

 <xsl:template match="*|PayloadFile"> is necessary otherwise the
previous template would snaffle PayloadFile that are private due to
its higher priority over a * pattern. So yes I am deliberately
exploiting the differing priorities of the union pattern to get the
outcome I desire which is that private PayloadFile elements should be
treated the same as public elements.


Regarding other use cases for keys in patterns - I tend to do my
renames like this

<xsl:key name="mapNames" match="ren:*/@to" use="../@from"/>
  <xsl:variable name="renames">
    <ren:element from="EmployeeCategory" to="Name"/>
    <ren:element from="PersonName" to="Name"/>
    <ren:element from="FormerlyKnown" to="Name"/>
     .
     .
   </xsl:variable>


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

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--