Subject: Re: [xsl] Best Way to Break Up Nested Structures Based On Inline Elements From: "Eliot Kimber ekimber@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Wed, 18 Apr 2018 21:19:36 -0000 |
Ken: I had forgotten about your PSMI. I'm coming back to FO after a long absence. Cheers, E. -- Eliot Kimber http://contrext.com o;?On 4/18/18, 4:01 PM, "G. Ken Holman g.ken.holman@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: There are a number of users of my Page Sequence Master Interleave (PSMI) code for the rotated tables: https://cranesoftwrights.github.io/resources/psmi/index.htm Perhaps this has some ideas you can exploit. . . . . . . Ken At 2018-04-18 20:36 +0000, Eliot Kimber ekimber@xxxxxxxxxxxx wrote: >I definitely owe Gerrit the beverage of his >choice. I was able to make this code work with my details. > >While it's not obvious (at least not to me--I >still need to take some time to fully appreciate >how it works) it's definitely much more elegant >than the recursive approach I was thinking of. > >I will probably also need to use this technique >to handle the challenge of changing page >sequences to render long rotated tables or foldout pages. > >When generating FO it's much eaiser logically to >emit page sequence start markers and then come >back and allocate things to page sequences than >it is to try to work out the page sequence >mapping when there's not a simple mapping from >top-level elements to page sequences. > >Cheers, > >Eliot >-- >Eliot Kimber >http://contrext.com > >C/B;B?On 4/18/18, 2:00 PM, "Imsieke, Gerrit, le-tex >gerrit.imsieke@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > > Hold my beer. > > <?xml version="1.0" encoding="UTF-8"?> > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > xmlns:xs="http://www.w3.org/2001/XMLSchema" > xmlns:fo="http://www.w3.org/1999/XSL/Format" > exclude-result-prefixes="xs" > version="2.0"> > > <xsl:output indent="yes"/> > > <xsl:template match="node() | @*" mode="#default split"> > <xsl:copy> > <xsl:apply-templates select="@* | node()" mode="#current"/> > </xsl:copy> > </xsl:template> > > <xsl:template match="fo:block[empty(ancestor::fo:block)]" > mode="#default"> > <xsl:variable name="block-root" as="element(fo:block)" select="."/> > <xsl:for-each-group select="descendant::node()[empty(node())]" > group-starting-with="two-column-start"> > <xsl:for-each-group select="current-group()" > group-ending-with="two-column-end"> > <xsl:apply-templates select="$block-root" mode="split"> > <xsl:with-param name="restricted-to" as="node()*" > select="current-group()/ancestor-or-self::node()" > tunnel="yes"/> > <xsl:with-param name="two-col-start" as="xs:boolean" > tunnel="yes" > select="exists(self::two-column-start)"/> > </xsl:apply-templates> > </xsl:for-each-group> > </xsl:for-each-group> > </xsl:template> > > <xsl:template match="node()" mode="split" priority="1"> > <xsl:param name="restricted-to" tunnel="yes" as="node()+"/> > <xsl:if test="exists(. intersect $restricted-to)"> > <xsl:next-match/> > </xsl:if> > </xsl:template> > > <xsl:template > match="fo:block[empty(ancestor::fo:block)]" mode="split"> > <xsl:param name="restricted-to" tunnel="yes" as="node()*"/> > <xsl:param name="two-col-start" tunnel="yes" as="xs:boolean"/> > <xsl:copy> > <xsl:apply-templates select="@*" mode="#current"/> > <xsl:if test="$two-col-start"> > <xsl:attribute name="span" select="'none'"/> > </xsl:if> > <xsl:apply-templates mode="#current"/> > </xsl:copy> > </xsl:template> > > <xsl:template match="two-column-start | two-column-end" mode="split"/> > > </xsl:stylesheet> > > > On 18/04/2018 20:23, Eliot Kimber ekimber@xxxxxxxxxxxx wrote: > > Gerrit, > > > > I don't immediately see how the code in > the referenced message works but it's simple enough to try in my context. > > > > In my case the number of switches is > small relative to the total content, so it will > only be applied occasionally and infrequently. > > > > Cheers, > > > > E. > > > > -- > > Eliot Kimber > > http://contrext.com > > > > C/B;B?On 4/18/18, 1:15 PM, "Imsieke, Gerrit, > le-tex gerrit.imsieke@xxxxxxxxx" > <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > > > > Hi Eliot, > > > > I think this can be tackled with > what I call "upward projection", see > > for ex. https://markmail.org/message/kmq2g4fidmw6cofz > > > > You'd identify all leaf elements and > group them (maybe a combination of > > group-starting-with="two-colum-start" and > > group-ending-with="two-colum-end" is in order here). > > > > Then for each group you transform > the top-level block in a certain mode, > > with a tunneled parameter. The > tunneled parameter contains the current > > group and its ancestors. > > > > In the template that matches any > element in this mode, you check whether > > the tunneled parameter contains the current element. If so, the > > next-match identity template will > apply, if not, nothing will be written > > to the result. > > > > There's a special template in this mode that matches the > > two-column-start element. It will > create <fo:block span="none"> and then > > go on processing the children. > > > > I'm not 100% sure whether this > works, but I have an intercontinental > > flight ahead of me. It will give me > some time to create working code, > > unless you're faster implementing > the suggested solution (or a better one). > > > > I guess that the solution scales > with the number of splitting points > > times the number of leaves, so > performance may deteriorate for large > > documents with frequently changing column spans. > > > > Gerrit > > > > On 18/04/2018 19:45, Eliot Kimber ekimber@xxxxxxxxxxxx wrote: > > > Using XSLT 2 with Saxon. > > > > > > In the context of generating > XSL-FO markup where there tree of fo:block > elements can be quite deep, I need to break the > blocks into a sequence of top-level blocks that > specify @span based on the presence of markers > anywhere in the heirarchy. This is to support > FOP's strict implementation of the FO spec, > which only allows specifying column spans on direct children of fo:flow. > > > > > > In my processing I'm emitting > marker elements to signal the starts and ends > of areas that need to change the column spanning, e.g.: > > > > > > <fo:block span="all"> > > > <fo:block> > > > <fo:block> > > > <fo:block> > > > <two-column-start/> > > > </fo:block> > > > ... > > > <two-column-end/> > > > </fo:block> > > > <fo:block>... > > > </fo:block> > > > </fo:block> > > > > > > Where the result needs to be: > > > > > > <fo:block span="all"> > > > <!-- Stuff before two-column start --> > > > </fo:block> > > > <fo:block span="none"> > > > <!-- Stuff up to <two-column-end/> marker --> > > > </fo:block> > > > <fo:block span="all"> > > > <!-- Stuff after <two-column-end> marker --> > > > </fo:block> > > > > > > There must be a general pattern > for solving this kind of transformation pattern > but I'm not seeing it or not remembering it. > > > > > > I can think of a recursive > algorithm to do it but is there a simpler or > more efficient approach? Conceptually it's a > for-each-group problem but the structure of the > content doesn't see to lend itself to grouping. > > > > > > Thanks, > > > > > > Eliot > > > -- > > > Eliot Kimber > > > http://contrext.com > > > > > > > > > -- Contact info, blog, articles, etc. http://www.CraneSoftwrights.com/s/ | Check our site for free XML, XSLT, XSL-FO and UBL developer resources | Streaming hands-on XSLT/XPath 2 training class @ US$45 (5 hours free) |
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Best Way to Break Up Nest, G. Ken Holman g.ken. | Thread | Re: [xsl] Best Way to Break Up Nest, Eliot Kimber ekimber |
Re: [xsl] Best Way to Break Up Nest, G. Ken Holman g.ken. | Date | Re: [xsl] Best Way to Break Up Nest, Eliot Kimber ekimber |
Month |