shish
shish

Reputation: 943

XSL FO transformation won't work if I have schema location inside XML file

My XSL-FO transformation will not work with XML specified below. It seems those xmlns and schemaLocation are bothering the transformation.

<book
xmlns="http://www.example.org/book"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/book book.xsd">

    <title>Something</title>
</book>

But if I rewrite my XML like below, the transformation runs smoothly and all my XPaths in the XSL are running good.

<book>
    <title>Something</title>
</book>

My question is: Is there some way to ignore those few lines of code which determine the schema location etc. ???

Thank you in advance!

Java class:

public static void generirajPDF() {
    try {

        // Setup directories
        File baseDir = new File(".");
        File outDir = new File(baseDir, "pdf");
        outDir.mkdirs();

        // Setup input and output files
        File xmlfile = new File(baseDir, "WebContent/AvtoSolaZ2.xml");
        File xsltfile = new File(baseDir, "WebContent/AvtoSolaZaposleniXSL.xsl");
        File pdffile = new File(outDir, "Test.pdf");

        // configure fopFactory as desired
        FopFactory fopFactory = FopFactory.newInstance();

        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
        // configure foUserAgent as desired

        // Setup output
        OutputStream out = new java.io.FileOutputStream(pdffile);
        out = new java.io.BufferedOutputStream(out);

        try {
            // Construct fop with desired output format
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

            // Setup XSLT
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory
                    .newTransformer(new StreamSource(xsltfile));

            // Set the value of a <param> in the stylesheet
            transformer.setParameter("versionParam", "2.0");

            // Setup input for XSLT transformation
            Source src = new StreamSource(xmlfile);

            // Resulting SAX events (the generated FO) must be piped through
            // to FOP
            Result res = new SAXResult(fop.getDefaultHandler());

            // Start XSLT transformation and FOP processing
            transformer.transform(src, res);

        } finally {
            out.close();
        }

        if (pdffile.toString().endsWith(".pdf"))
            Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + pdffile);
        else {
            Desktop desktop = Desktop.getDesktop();
            desktop.open(pdffile);
        }

        System.out.println("Konec");

    } catch (Exception e) {
        e.printStackTrace(System.err);
        System.exit(-1);
    }
}

Upvotes: 0

Views: 1343

Answers (3)

Michael Kay
Michael Kay

Reputation: 163342

This question is asked about once a day. Just search for "XSLT default namespace". Putting your elements in a namespace changes their names, and the transformation will only find them if it looks in the right namespace.

Upvotes: 0

Martin Honnen
Martin Honnen

Reputation: 167571

If you use an XSLT 2.0 processor to run your XSLT then set

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transformation"
  xpath-default-namespace="http://www.example.org/book"
  version="2.0">

on the root element of the stylesheet and you don't need to change the match patterns and XPath expressions in the code.

If you use an XSLT 1.0 processor you need to rewrite your code to cater for the namespace by doing e.g.

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transformation"
  xmlns:df="http://www.example.org/book"
  exclude-result-prefixes="df"
  version="1.0">

<xsl:template match="df:book">
  <xsl:value-of select="df:title"/>
</xsl:template>

Upvotes: 2

If your XML input is

<book  xmlns="http://www.example.org/book" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/book book.xsd">
<title>Something</title>
</book>

and the stylesheet is

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*[local-name()='book']">
    <root>Matched the root with name space why not others</root>
</xsl:template>
</xsl:stylesheet>

and your output will be like

<?xml version="1.0" encoding="UTF-8"?>
<root>Matched the root with name space why not others
</root>

The local-name() function is part of XSLT 1.0 (http://www.xsltfunctions.com/xsl/fn_local-name.html) that matches only the element name without the namespace.

Upvotes: 0

Related Questions