[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
[Recent Entries]
[Reply To This Message]
Re: Best Way to Break Up Nested Structures Based On I
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
o;?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
>
> o;?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) |
|
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format
RSS 2.0 |
|
Atom 0.3 |
|
|