James,
At 07:25 PM 4/14/2003, you wrote:
Turns out that the above doesn't *quite* work because
a div1 may have a sibling that is a div1. Easy enough
problem to fix, though, at least by a combination of
"for-each" and "if".
Not the best way to go about fixing though. Set up the key to be what you
actually want.
In your case, my guess it'll probably be something along the lines of:
<xsl:key name="top-levels-by-div"
match="body/*[not(starts-with(local-name(), div))]"
use="generate-id((preceding-sibling::div|preceding-sibling::div0|preceding-sibling::div1)[last()])"/>
It matches all child elements of body that are not themselves divs, and
uses as the key value the generated id of the most recent div, div0 or div1.
div2, div3 etc. we don't have to worry about since they can't occur at the
top level.
If you never had div0 or div1 (ie if your source were normalized to plain
divs), this could be
<xsl:key name="top-levels-by-div"
match="body/*[not(self::div)]"
use="generate-id(preceding-sibling::div[1])"/>
Assuming this case (since it's simpler) your implementation pattern would be:
<xsl:template match="body">
<fo:page-sequence>
<xsl:apply-templates select="key('top-levels-by-div','')"/>
<!-- gets top-level nodes not preceded by a div -->
</fo:page-sequence>
<xsl:apply-templates name="div"/>
</xsl:template>
<xsl:template match="div">
<fo:page-sequence>
<xsl:apply-templates/>
<!-- invite the kids -->
<xsl:apply-templates select="key('top-levels-by-div', generate-id())"/>
<!-- invite the orphan nodes that directly follow this div -->
</fo:page-sequence>
</xsl:template>
Still, I wish I knew why
<xsl:key name="x"
match="node()[not(starts-with(name(), div))]"
use="generate-id((..|preceding-sibling::div1|
preceding-sibling::div2|preceding-sibling::div3)[last()])"/>
doesn't work
The nodes you're worried about (nodes under body, perhaps under front or
back, which I've left out of scope) won't have preceding siblings that are
div2 or div3, since the only kinds of divs allowed there are div, div0 or
div1. (This is a design flaw, IMHO, but there you are; the TEI as so often
is trying to be ecumenical.)
If your top-level divs are div0s, this key won't match a milestone element
to the div0 that directly precedes it ... etc. etc.
(And you'll have to forgive David for not having memorized the TEI DTD; I
think MathML is probably enough of an accomplishment.)
doesn't work, or why the following doesn't do what the
xsl:key line you gave me does:
<xsl:key name="x" match="node()"
use="generate-id(..|preceding-sibling::div1[1]|
preceding-sibling::div2[1]|preceding-sibling::div3[1])"/>
The generated id here belongs to the *first* (in document order) of either
the parent, most immediately preceding div1, div2 or div3. You want the
most recent one. The explanation for why this is may be found in an XPath
manual that explains that when generate-id() is used on a node set, it
returns the generated id for the first node in the set in document order.
You want the generated id of the last.
I hope that helps. If confusion persists, perhaps we should mock up a
mini-sample instance to demonstrate the problem. Or maybe three of them:
one for each kind of top-level div.
Cheers,
Wendell
======================================================================
Wendell Piez
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
----------------------------------------------------------------------
Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list