[xsl] xpath key problems: follow-up

Subject: [xsl] xpath key problems: follow-up
From: "Birnbaum, David J" <djbpitt@xxxxxxxx>
Date: Thu, 25 Nov 2010 16:42:55 -0500
Dear XSLT List,

Thanks to those who replied to my inquiry about keys and grouping. To follow
up:

1. As Piet pointed out, I had swapped the @match and @use values, confusing
whether I was specifying what was being used when the key was constructed with
what was used when it was called. Sigh.

2. As Martin pointed out, I had also confused what was being passed by the
<xsl:key> element. I had thought it was the element itself (that is, the
element object), while it was actually the atomized string value of the
element. I would have needed Piet's strategy of using generate-id to construct
a pointer to the element.

3. Keys pay off when reused, but if I'm going to access each value only once,
there's no economy in doing that by constructing a key as opposed to doing it
in the template itself.

4. I had originally constructed an XPath that collected the preceding elements
that had the same name value as the current one and then looked inside them
for <pb> elements. This was unacceptably slow, but I got an responably peppy
response by instead collecting the preceding <pb> elements and then using a
predicate to filter out the ones that have a different parent than the current
element:

	preceding::pb[parent::*[name() eq current()/name()]][1]/@folio

5. Counting lines (<lb> elements) from the most immediately preceding <pb>
through the current position required a compound predicate that specified
three things:

	a. Before the current position. Use the preceding axis.
	b. After the most immediately preceding page break. Use the <pb> identified
above.
	c. Same parent as the current element. Specify this in the predicate.

Put together:

    <xsl:template match="hm280 | hm281 | hm282">
        <!-- $foliopointer is the most immediate preceding pb
            requires special treatment for first line, which has no preceding
pb -->
        <xsl:variable name="foliopointer"
            select="if (preceding::block) then preceding::pb[parent::*[name()
eq current()/name()]][1]/@folio
            else pb/@folio"/>
        <!-- $linepointer is count of lb elements between $foliopointer and
            current position -->
        <xsl:variable name="linepointer"
            select="1 + count(preceding::lb[parent::*[name() eq
current()/name()] and
            preceding::pb[parent::*[name() eq current()/name()]][1]/@folio eq
$foliopointer])"/>

This lets me generate the page/line identifiers I need. Thanks again to those
whose responses pushed me back on the right track.

Sincerely,

David (djbpitt@xxxxxxxx)

Current Thread