Re: [xslt] key() behavior changed between 11 and 13?



> The behavior of keys changed between somewhere between version 11 and
> 13.

This is true.  Ref Changelog in libxslt-0.12.0:
Sun Jun 10 13:37:33 HKT 2001 William Brack <wbrack@mmm.com.hk>

        * libxslt/transform.c: fixed problems with document() in
          xsltApplyTemplates and xsltForEach.  Cleaned up several
          error messages.
        * libxslt/keys.c: saved and restored ctxt->document within
          xsltInitKey to fix problem with keys when doc changed

> Because I'm dealing with a large (3 meg) XML document, I run a
> preliminary script to generate a "map" of the original document, which
> is essentially all the titles of various sections with some metadata,
> in the same nested structure as the original document.
>
> When I parse the original document, I create a key on <author>s and
> then <section>s. Pretty standard stuff:
>
>   <!-- for the authors and quoted-->
>   <xsl:key
>     name="key_person"
>     match="//person" use="@id"/>
>
>   <!-- for the sections-->
>   <xsl:key
>     name="key_section"
>     match="//section" use="@id"/>

This is good, and a good approach.

> HOWEVER I then load in the "map" XML document using the "document()"
> function and begin to step through /that/ instead of the original
> document. With each <section> of the "map" document I do a key lookup
> on the same <section> in the main document and apply some standard
> templates.
>
>   <xsl:apply-templates select="key('key_section', $frontpage)"
>   mode="build"/>
>
> Where $frontpage is the value of an @id attribute inside a <section>
> tag. This approach allows for a speedup of roughly 100x vs. traversing
> the original document tree to pull out navigation information.

This is not quite so good.  Your problem is that the 'key' in the select is
referring to the 'current' document (your 'map' document) and not the
'original' document.

> Anyway - this cross-document key-lookup worked in version 11, broke in
> 12, and continues to return 0 nodes per lookup in 13. Any suggestions?
> Did something break, or is my approach wrong and shouldn't have worked
> in the first place?

Now you are embarassing me ;-)  (it shouldn't have worked in the first
place)

Basically, your problem is that you are working with one document and want
to do something with a different document.  There are only two ways to
change the 'current' document - apply-templates and for-each.  One possible
approach to solve your particular example would be to declare a global
(note global, not local) variable to identify the 'original' document:

<xsl:variable name="root" select="/"/>

and then surround your 'apply-templates' with a 'for-each':

<xsl:for-each select="$root"> <!-- causes document change -->
   <xsl:apply-templates select="key('key_section', $frontpage)"
       mode="build"/>
</xsl:for-each>

> Thanks for all your work!
>
> Paul Ford

Sorry for the trouble you encountered - hope this helps.

Bill Brack





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]