Subject: RE: 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: 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
>
> ---
|