xsl-list
[Top] [All Lists]

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

2018-04-18 16:27:12
The only refinement I had to add was a post-process to remove duplicate IDs. I 
couldn't immediately think of a way to determine that a give @id attribute was 
being handled for the first time during the split process, so easier to just 
filter out duplicates as a follow-on process.

Cheers,

E.
--
Eliot Kimber
http://contrext.com
 
On 4/18/18, 3:35 PM, "Eliot Kimber ekimber(_at_)contrext(_dot_)com" 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_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
        >      >
        >      >
        >      >
        >      
        >      --
        >      Gerrit Imsieke
        >      Geschäftsführer / Managing Director
        >      le-tex publishing services GmbH
        >      Weissenfelser Str. 84, 04229 Leipzig, Germany
        >      Phone +49 341 355356 110, Fax +49 341 355356 510
        >      gerrit(_dot_)imsieke(_at_)le-tex(_dot_)de, http://www.le-tex.de
        >      
        >      Registergericht / Commercial Register: Amtsgericht Leipzig
        >      Registernummer / Registration Number: HRB 24930
        >      
        >      Geschäftsführer / Managing Directors:
        >      Gerrit Imsieke, Svea Jelonek, Thomas Schmidt
        >      
        >      
        >      
        > 
        > 
        
        -- 
        Gerrit Imsieke
        Geschäftsführer / Managing Director
        le-tex publishing services GmbH
        Weissenfelser Str. 84, 04229 Leipzig, Germany
        Phone +49 341 355356 110, Fax +49 341 355356 510
        gerrit(_dot_)imsieke(_at_)le-tex(_dot_)de, http://www.le-tex.de
        
        Registergericht / Commercial Register: Amtsgericht Leipzig
        Registernummer / Registration Number: HRB 24930
        
        Geschäftsführer / Managing Directors:
        Gerrit Imsieke, Svea Jelonek, Thomas Schmidt
        
        
        
    
    
    
--~----------------------------------------------------------------
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>