XSL-FO

XSL Formatting Objects (XSL 1.1, W3C Recommendation 5 December 2006) describe printed pages: page masters, flows, blocks, tables. An XSLT stylesheet turns data into FO, and a formatter such as Apache FOP 129 (xmlgraphics.apache.org/fop (https://xmlgraphics.apache.org/fop/ 129 ), Apache-2.0; 2.11, May 2025) lays it out as PDF. This one prints a price card with dot leaders:

pricelist.xsl: an XSLT 3.0 stylesheet that writes XSL-FOXML
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fo="http://www.w3.org/1999/XSL/Format" expand-text="yes">
  <xsl:template match="/catalog">
    <fo:root>
      <fo:layout-master-set>
        <fo:simple-page-master master-name="card" page-width="148mm" page-height="105mm"
            margin="12mm"><fo:region-body/></fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="card">
        <fo:flow flow-name="xsl-region-body" font-family="Helvetica" font-size="11pt">
          <fo:block font-size="16pt" font-weight="bold" space-after="4mm">Prices</fo:block>
          <xsl:for-each select="book">
            <fo:block text-align-last="justify" space-after="2mm">{title}
              <fo:leader leader-pattern="dots"/> ${.//price}</fo:block>
          </xsl:for-each>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>
</xsl:stylesheet>
Saxon makes the FO, FOP makes the PDF
xslt3 -s:booknest-catalog.xml -xsl:pricelist.xsl -o:pricelist.fo
~/xml-tools/fop-2.11/fop/fop -q -fo pricelist.fo -pdf pricelist.pdf 2> /dev/null
pricelist.pdf, rendered at 110 dpi
pricelist.pdf, rendered at 110 dpi

FOP's own -xsl option uses the JDK's XSLT 1.0 processor, which rejected this stylesheet ("Illegal attribute 'expand-text'"), hence the Saxon 726,956 step. Commercial formatters (Antenna House, RenderX XEP) cover more of XSL-FO; CSS Paged Media tools such as WeasyPrint compete for new projects.


XSL FO

Extensible Stylesheet Language – Formatting Objects (XSL-FO), also referred to as XSL, is a markup language for formatting XML data for output to screen, paper, or other media.

XSL-FO transformation pipeline: XML and XSL feed an XSLT engine (Saxon or Xalan) producing an XSL-FO document, which an XSL-FO formatter (Apache FOP or RenderX) renders to PDF, PCL, TeX, PS, or RTF for printing
An XML document and an XSL stylesheet are fed into an XSLT engine (such as Saxon 726,956 or Xalan), which produces an XSL-FO document. That XSL-FO document is then fed into an XSL-FO formatter (such as Apache FOP or RenderX), which renders the final output as PDF, PCL, TeX, PS, or RTF, ready for printing.

The following defines a simple page master and a two-block page body.
ch12-xslfo-simple-page.foXML
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <fo:layout-master-set>
      <fo:simple-page-master master-name="simple"
              page-height="11in" page-width="8.5in"
              margin-top="1.0in" margin-bottom="1.0in"
              margin-left="1.25in" margin-right="1.25in">
         <fo:region-body margin-top="0.25in" />
      </fo:simple-page-master>
   </fo:layout-master-set>
   <fo:page-sequence master-reference="simple">
      <fo:flow flow-name="xsl-region-body">
         <fo:block font-size="18pt" font-family="sans-serif"
               line-height="24pt" space-after.optimum="15pt"
               background-color="blue" color="white"
               text-align="center" padding-top="3pt">
              Title
         </fo:block>
         <fo:block font-size="12pt" font-family="sans-serif"
                       line-height="15pt" space-after.optimum="3pt"
                       text-align="justify">
               Some Text
         </fo:block>
      </fo:flow>
   </fo:page-sequence>
</fo:root>