xsl-list
[Top] [All Lists]

Re: [xsl] Best Way to Break Up Nested Structures Based On Inline Elements

2018-04-18 16:19:41
Ken: I had forgotten about your PSMI. I'm coming back to FO after a long 
absence.

Cheers,

E.

--
Eliot Kimber
http://contrext.com
 
On 4/18/18, 4:01 PM, "G. Ken Holman 
g(_dot_)ken(_dot_)holman(_at_)gmail(_dot_)com" 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 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(_at_)contrext(_dot_)com 
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
    >
    >On 4/18/18, 2:00 PM, "Imsieke, Gerrit, le-tex 
    >gerrit(_dot_)imsieke(_at_)le-tex(_dot_)de" 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 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(_at_)contrext(_dot_)com 
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
    >     >
    >     > On 4/18/18, 1:15 PM, "Imsieke, Gerrit, 
    > le-tex gerrit(_dot_)imsieke(_at_)le-tex(_dot_)de" 
    > <xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 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(_at_)contrext(_dot_)com 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) |
    
    
    
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

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