RE: [xsl] A tricksy XSL question: key(name,match,use="contains()")

Subject: RE: [xsl] A tricksy XSL question: key(name,match,use="contains()")
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Sun, 28 Aug 2005 23:43:31 +0100
In 2.0 you can do

<xsl:key .... use="tokenize(@ids, '\s')"/>

In 1.0 you could use the exslt:tokenize function in a similar way, but if
you know that the maximum number of tokens is 2, Jeni's solution is more
portable.

Michael Kay
http://www.saxonica.com/

 

> -----Original Message-----
> From: David Priest [mailto:priest@xxxxxx] 
> Sent: 28 August 2005 21:54
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] A tricksy XSL question: 
> key(name,match,use="contains()")
> 
> After extensive web searching, I can not find a direct answer 
> to this  
> problem (which, I rather suspect, means it is not solvable -- at  
> least, not using the approach I'm attempting!).
> 
> I have an XML file in which sections are given an "@ids" attribute  
> which look just like this:
>    <section ids="this-is-an-unfriendly-id  this-is-the-friendly-id">
> 
> I need to identify the page on which the section starts, ie. for in- 
> text references to that section.
> 
> In those cases where the section contains only a single ID, the  
> following works:
>    <xsl:key name="sectionkey" match="section" use="@ids" />
>    <fo:page-number-citation ref-id="{key('sectionkey', @refid)/./ 
> @ids}" />
> 
> However, as shown above, some sections have two ids (one from the  
> actual title as written, and an abbreviated one that will 
> continue to  
> work even if someone were to change the title).  Thus, I need to  
> modify the XSL so that if @ids *contains* the refid, it is a match.   
> Something like -- but this doesn't work! -- the following:
>    <xsl:key name="sectionkey" match="section" use="contains(@ids,  
> $refid)" />
>    <fo:page-number-citation ref-id="{key('sectionkey', 
> contains(@ids,  
> @refid)/./@ids" />
> 
> Is there a solution to this problem?  Either way, it should probably  
> appear in the FAQ,
>    http://www.dpawson.co.uk/xsl/sect2/N4852.html
> 
> Any hints and tips appreciated.
> 
> Footnote: Jeni's answer follows.  I am documenting this question and  
> answer for future reference; please do add your solutions, too!
> 
> Hi David,
> 
> > However, as shown above, some sections have two ids (one from the
> > actual title as written, and an abbreviated one that will 
> continue to
> > work even if someone were to change the title).  Thus, I need to
> > modify the XSL so that if @ids *contains* the refid, it is a match.
> >
> 
> As you've found, you can only use keys to locate nodes whose key value
> *exactly equals* a value you're searching for: you can't use
> contains() semantics.
> 
> All that means is that, in general, you need to use normal XPath
> expressions to get at the relevant section, as in something like:
> 
>    <fo:page-number-citation
>      ref-id="{//section[contains(@ids, $refid)]}" />
> 
> (though probably not that, since you don't want all the content of the
> <section> element within the ref-id attribute).
> 
> However, what you have is a more specialised situation, where a
> <section> can either have one or two ids in the ids attribute, and if
> there are two then they are space-separated. That being the case, you
> can construct a sectionkey key that indexes each of the sections by
> the appropriate ID using string manipulation functions. For example:
> 
> <!-- sections that only have one id are indexed by that id -->
> <xsl:key name="sectionkey"
>           match="section[not(contains(@ids, ' '))]"
>           use="@ids" />
> 
> 
> <!-- sections that have two ids are indexed by the first and the
>       second -->
> <xsl:key name="sectionkey"
>           match="section[contains(@ids, ' ')]"
>           use="substring-before(@ids, ' ')" />
> <xsl:key name="sectionkey"
>           match="section[contains(@ids, ' ')]"
>           use="substring-after(@ids, ' ')" />
> 
> Then you can do:
> 
>     <fo:page-number-citation ref-id="{key('sectionkey', @refid)}" />
> 
> as normal.
> 
> Cheers,
> 
> Jeni
> 
> ---

Current Thread