Adapt Saxon-CE event model to XSL-FO?

(I first wrote this as a blog post for my personal blog just so it can
show signs of life.)

I've been reading about how Saxon-CE [1] handles user input, and I'm now
wondering whether the same sort of pattern could be adapted to handling
feedback from the XSL formatter.  Saxon-CE does it [2] through template
rules that match the element that receives the event and are in a mode
that reflects the type of event, and similarly an XSL formatter could
trigger on exceptional events such as overflow occurring or even on
mundane events such as completion of a page sequence, and the templates in
the corresponding modes could match on either FOs in the FO tree or areas
in the area tree.

The XSL-FO 2.0 Requirements [3] document includes, among others,
requirements for: feedback from the pagination stage [4]; including
information from formatting time [5]; and outputting the result of an
expression [6] back into the area tree.  However, the XML Print and Page
Layout Working Group never got to the point of working out how any of
those would be expressed.

More recently, we, the 'ppl', have been collecting examples where feedback
from the formatter is useful [7] – or essential – for a satisfactory
result.  Thanks to Arved we also have a proof-of-concept [8] for running a
XSL formatter from a XSLT extension function to get an area tree, so an
XSLT stylesheet can now make decisions about what to put in the result
based on the trial formatted size of areas, but as it's only a
proof-of-concept, it doesn't aim as high as getting feedback from or
modifying in-situ the area tree for the final, formatted document.

Once people have tried a few things with getting feedback from the XSL
formatter and start asking their vendors for the same or better, they'll
also be wanting an interoperable way to express what to do with that
feedback.  For simple feedback of static area trees, which is all that is
possible with the current proof-of-concept, the most interoperability that
you could manage would be a common representation of area trees (with
flexibility for vendor extensions) and, possibly, a library of XSLT
functions to make it easier to navigate the area trees, but for "live"
feedback, something more would be required.

The following template from the "Knight's Tour" [9] sample Saxon-CE
application is the event handler for when the user clicks the 'Reset'
button.  It simply writes a NO-BREAK SPACE to each square on the Knight's
chess board

<xsl:template match="button[@id='reset']" mode="ixsl:onclick">
  <xsl:for-each select="//div[starts-with(@id, 'square')]">
     <xsl:result-document href="#{@id}" method="replace-content">
       <xsl:text>&amp;#xa0;</xsl:text>
     </xsl:result-document>
  </xsl:for-each>
</xsl:template>

The key feature of the event handler for the purposes of this discussion
is that it's written in plain old XSLT.  The advantage of the XSLT event
handler for Saxon-CE users is interactivity "without dropping down into
JavaScript" (as the Saxon-CE documentation [10] so delicately puts it),
but the advantage for XSL-FO users would simply be that they don't need to
learn a new language (declarative, functional, or otherwise) to handle
feedback.  (And the advantage for those of us trying to define or
implement feedback is that we don't need to invent a whole new language to
handle it.)

Applying the Saxon-CE approach to XSL-FO, the following illustrative FO
event handler would handle a figure overflowing its available space by
reducing its size to 80% of the current.

<xsl:template match="BlockArea[key('fig', @id, $src-doc)]"
              mode="ppl:overflow">
  <xsl:result-document href="#{@id}/area:external-graphic"
                       method="replace-content">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="width"
                     select="ppl:scale(area:external-graphic/@width,
                                       0.8)"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:result-document>
</xsl:template>

(I invented a <code>ppl:scale()</code> XSLT extension function here so the
new length is written back to the area tree rather than requiring that XSL
formatters support an expression language in area tree trait values.)

An extra wrinkle for XSL-FO is the question of whether event handlers
should be specified to (a) match on, and (b) modify the FO tree or the
area tree or both.  There are some existing requirements that can only be
satisfied by modifying the area tree, e.g., Section 3.3, Output result of
expression [6]:

   Allow users to output the result of expressions on area tree,
   traits, markers or text content. For example to calculate the
   subtotal of a certain page (as opposed to a running total that
   is already supported in XSL 1.1 with table markers)

On the other hand, it will often be simpler (from the user's perspective)
to modify an FO rather than all the areas that it generates, since a
single FO may generate multiple areas across several columns or pages (and
footnote areas), and its content may be reused in markers on multiple
pages.  If, for example, the response to a page sequence taking too many
pages is to reduce the font size in one of the multiple flows appearing on
the page, it would be at once simple to adjust the 'font-size' property on
the appropriate FOs in the FO tree and inaccurate to directly modify font
sizes in the line areas in the area tree.  If the XSL formatter did the
work based on modified FOs, it would reflow the line areas based on their
reduced font size and make the pages again and the resulting modified
block areas would break across pages in different places because of the
smaller font size.  If the XSLT stylesheet did the work by modifying the
area tree, it would have to do the same recalculating of text sizes and
the same merging or splitting of line areas and of block areas, and all
(probably) without the benefit of font metrics.  It might work, just, in a
simple case with only monospace fonts, but would still be a lot of work to
do in XSLT.

Adapting the Saxon-CE event model to XSL-FO is, therefore, an interesting
possible solution to handling feedback from the XSL formatter, but there
are still many FO-specific details that would have to be worked out.

Regards,


Tony.

[1] http://www.saxonica.com/ce/user-doc/1.1/index.html
[2] http://www.saxonica.com/ce/user-doc/1.1/index.html#!about/design
[3] http://www.w3.org/TR/xslfo20-req/
[4] http://www.w3.org/TR/xslfo20-req/#N66678
[5] http://www.w3.org/TR/xslfo20-req/#N66711
[6] http://www.w3.org/TR/xslfo20-req/#output-result-of-expression
[7] http://www.w3.org/community/ppl/wiki/CustomerRequirements
[8] http://lists.w3.org/Archives/Public/public-ppl/2013Mar/0036.html
[9] http://www.saxonica.com/ce/user-doc/1.1/index.html#!samples/tour
[10] http://www.saxonica.com/ce/user-doc/1.1/index.html#!coding/events

Received on Wednesday, 17 April 2013 12:54:43 UTC