Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a beginner question on XSLT

Tags:

xslt

xsl-fo

saxon

I just started learning XSLT,now I am following some on-line tutorial of it,and I just have a simple question now:

suppose we have a original xml file,do we need to write a XSLT Stylesheet to go with it,or do we just simply pass the xml file into some software like Stylus Studio(Saxon Engine),then it will do all these things automatically for us?

Sorry for the mis clarification.I need to convert this .svg file to a pdf,I am just now at the beginning of the development,so really confused about the first step.Also,I would like to know,if my initial input is a .svg file,do I have to explicitly transform it into an .xml before I can start using XSLT?

Thanks in advance!

like image 810
Kevin Avatar asked Jan 21 '23 03:01

Kevin


1 Answers

Sorry for the mis clarification.I need to convert this .svg file to a pdf,I am just now at the beginning of the development,so really confused about the first step.Also,I would like to know,if my initial input is a .svg file,do I have to explicitly transform it into an .xml before I can start using XSLT?

An SVG file is an XML file in the SVG namespace. Whether or not you need to transform that XML depends on how you're going to use it. If you were going to do a batch print using something like Inkscape (an SVG editor), you wouldn't.

If you are going to use something like XSL-FO, you would. The answer by @Zoltan Hamori is kind of misleading. You can use saxon to perform an XSLT transform (creating the XSL-FO), but you will still need an XSL-FO processor to create the PDF from the XSL-FO.

Zoltan mentions FOP (Apache Formatting Objects Processor), but he makes it sound like FOP and XSL-FO are the same; they're not. His code example is an XSL-FO table (XML in the fo namespace). You would need a processor such as FOP, RenderX, Antenna House, etc. to create the PDF from the XSL-FO.

Basically what you need is:

  1. XML input (this would be your SVG file)
  2. XSLT transform to create the XSL-FO.
  3. XSL-FO processor to create the PDF from the XSL-FO

Learning the XSL-FO at the same time you're learning XSLT is going to be tough, but I will show you two ways to output an SVG in a PDF.

The first way is to reference the SVG file using fo:external-graphic.

The second way is to embed the SVG XML directly into the XSL-FO using fo:instream-foreign-object.

Since the XML input is the SVG XML, I would go with the second option. However, I'm not sure what effect this has on processing time and which way would be more efficient.

I've shown an example below. Since I showed both ways to output an SVG, this will create a 2 page PDF. Each page will have the SVG graphic.

Notes

  • For testing, I used an example SVG file that came with Inkscape. (I removed most of the SVG XML from the XSL-FO output because it's pretty big.)
  • For my XSLT processor, I used Saxon-HE 9.2.0.6.
  • For my FO processor, I used Apache FOP Version 0.95 (although I much prefer RenderX).

Also

  • Both Saxon-HE and Apache FOP are free.
  • If you give me your email, I can send you the SVG file I used along with the full XSL-FO output. I can also send you the PDF that was created.

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- 
    This is an "identity" template.
    It copies whatever node from input to the output without changing it. 
    Learn it. Use it. Love it. -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">
    <fo:root>
      <fo:layout-master-set>
        <fo:simple-page-master master-name="my-page">
          <fo:region-body/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="my-page">
        <fo:flow flow-name="xsl-region-body">
          <fo:block>
            <!-- This is the first way to output an SVG; by referencing the graphic. -->
            <fo:external-graphic src="test.svg"/>
            <!-- This is the second way to output an SVG; by outputting the SVG XML directly. -->
            <fo:instream-foreign-object>
              <xsl:apply-templates/>
            </fo:instream-foreign-object>
          </fo:block>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>

</xsl:stylesheet>

XSL-FO (created by Saxon from SVG input and XSL stylesheet)

<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
   <fo:layout-master-set>
      <fo:simple-page-master master-name="my-page">
         <fo:region-body/>
      </fo:simple-page-master>
   </fo:layout-master-set>
   <fo:page-sequence master-reference="my-page">
      <fo:flow flow-name="xsl-region-body">
         <fo:block>
            <fo:external-graphic src="test.svg"/>
            <fo:instream-foreign-object>
              <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                    version="1.1"
                    width="595.99438"
                    height="491.50516"
                    id="svg2675">
                <!-- CONTENT REMOVED FOR STACKOVERFLOW.COM EXAMPLE -->
              </svg>
            </fo:instream-foreign-object>
         </fo:block>
      </fo:flow>
   </fo:page-sequence>
</fo:root>

Hope this helps.

like image 149
Daniel Haley Avatar answered Jan 27 '23 18:01

Daniel Haley