xsl-list
[Top] [All Lists]

Re: [xsl] Targeting nodes between <lb/> elements

2008-04-27 21:47:43
I have a similar problem in that I have to process books which can have page markers at any level of the content. What I ended up doing was building a two-step process - one which reformats the text such that the "separators" (the <lb/> elements in your case) are all at the same level, and then a second step which performs the actual work needed (generating <fo:block>elements in your case). I had a common root element that I could work backwards to using the ancestor axis to close all of the open tags up to that point by writing closing tags with <xsl:text>; I then wrote my "separator" and then worked forward from that element using the same axis to re-open all of the previously-open tags using <xsl:text>. It's very rough and probably violates many principles of XSLT, but it works.

In essence, the logic is:

<xsl:template match="lb">
for each ancestor between current node and a common root node (working backwards from current node's parent to common root) .. write a fake closing element node using <xsl:text: disable-output- escaping="true">
end for each

write <lb/> node

for each ancestor between current node and a common root node (working forwards from common root to current node's parent) .. write a fake opening element node using <xsl:text: disable-output- escaping="true"> with note that generated open node is a "fake"
end for each
</xsl:template>

What you'd end up with as a result of this first step, based on your example, is:

<root>
<lb/>
<sp><speaker>speaker1</speaker><p>text1</p></sp>
<lb/>
<sp fake="yes"><p fake="yes">text2</p></sp>
<lb/>
<sp><speaker>speaker2</speaker><p>text3</p></sp>
<lb/>
<sp fake="yes"><p fake="yes">text4</p></sp>
<lb/>

This could then be processed pretty easily using <xsl:for-each- group>, which I think would look something like this (not tested):

<xsl:for-each-group select="*" group-starting-with="lb">
<fo:block>
<xsl:for-each select="current-group()">
... call templates to write <fo:inline> or text as appropriate ...
</xsl:for-each>
</fo:block>
</xs:for-each-group>

Your results may vary :)

I too would be interested to see if there's a more elegant, non- kludgy way of solving this problem.


Cheers
Chris

On Apr 27, 2008, at 8:45 PM, xsl-list(_at_)diegesis(_dot_)net wrote:
Hello all,

I've been lurking for a while, and would like first to express my thanks to all of the experts here who are so incredibly generous with their expertise.

I've been banging my head (painfully) against what seems to me should be a relatively simple issue. I've tried to find the solution in the obvious books and in the archives of this list, but at this point am completely demoralised by repeated failure. I'd be extremely grateful for any help in getting past this hurdle.

I'm trying to wrap in an <fo:block> the nodes between pairs of <lb/ > elements. These nodes are not all siblings:

[source]
<lb/><sp><speaker>speaker1</speaker><p>text1
<lb/>text2</p></sp>
<lb/><sp><speaker>speaker2</speaker><p>text3
<lb/>text4</p></sp>

[desired output]
<fo:block><fo:inline>speaker1</fo:inline>text1</fo:block>
<fo:block>text2</fo:block>
<fo:block><fo:inline>speaker2</fo:inline>text3</fo:block>
<fo:block>text4</fo:block>

Also, I need to be able to further process some elements in each matched sequence (such as the <speaker> shown in the example). None of these elements will contain <lb/>.

Using XSLT 2.0 and Saxon 9B (and XEP), I've tried countless approaches involving for-each-group or simple XPath predicates ( << and >> ). Problems have ranged from matching problems to looping problems (Saxon error: "Too many nested apply-templates calls. The stylesheet may be looping.").

Many thanks in advance for any help you can send my way. At this point I'm fully prepared to be mortified by the inevitable simplicity of the solution...

Kitto

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>