Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic doctype in XSLT transform (correct use of result-document instruction)

Tags:

xslt

xslt-2.0

I'm using XSLT and need to generate the doctype dynamically in the transformed output, based on a parameter. I hear that this cann't be done using XSLT 1.0, but can with version 2.0, using the result-document tag.

So far, from following the answer in this question, I have something like this:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html" indent="yes"/>
    <xsl:param name="doctype.system" select="'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'" />
    <xsl:param name="doctype.public" select="'-//W3C//DTD XHTML 1.0 Strict//EN'" />
    <xsl:template match="/">
    <xsl:result-document doctype-public="{$doctype.public}" doctype-system="{$doctype.system}" method="html">
       <html>
          <head>
            <xsl:apply-templates select="report/head/node()"/>
          </head>
          <body>
             <!-- ommitted for brevity -->
          </body>
       </html>
    </xsl:result-document>
    </xsl:template>
    </xsl:stylesheet>

The problem with the above is no output is generated!

If I remove the results-document tags from the above, my transform is applied and a document is output, as expected.

Any clues? Am I using the result-document tag correctly?


UPDATE: In response to some of the comments here's a small version that works, and one that doesn't (omitting the parameterisation of the result-document instruction)

This works (no result-document):

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" indent="yes"/> 
<xsl:template match="/">
   <html>
      <head>

      </head>
      <body>

   </body>
   </html>   
</xsl:template>
</xsl:stylesheet>

Output:

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body></body>
</html>

But this produces no output:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" indent="yes"/> 
<xsl:template match="/">
<xsl:result-document doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" method="html">
   <html>
      <head>

      </head>
      <body>

   </body>
   </html>
</xsl:result-document>   
</xsl:template>
</xsl:stylesheet>
like image 953
Joel Avatar asked Dec 18 '25 05:12

Joel


1 Answers

As you also found out, Xalan only supports XSLT 1.0, but if you've changed to Saxon 9, you could easily achive what you want.

Also, instead of defining parameters with your doctype settings, you could define a xsl:output with a name and use as a format in xsl:result-document:

<xsl:output name="my-xhtml-output" method="xml" encoding="UTF-8" indent="yes"
  doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>

In your xsl:result-document you then use this output format:

<xsl:result-document href="{$filename}" format="my-xhtml-output">
  ...
</xsl:result-document>

Imo, this makes it easier to maintain different output formats if you have lots of them.

like image 61
Per T Avatar answered Dec 21 '25 07:12

Per T



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!