Dynamic doctype in XSLT transform (correct use of

2019-07-06 04:07发布

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>

标签: xslt xslt-2.0
2条回答
在下西门庆
2楼-- · 2019-07-06 04:50

As you are using an XSLT 1.0 engine you will have to create the dynamic DOCTYPE using xsl:text:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <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:text disable-output-escaping='yes'>&lt;!DOCTYPE html PUBLIC "</xsl:text>
      <xsl:value-of select="$doctype.public" />
      <xsl:text disable-output-escaping='yes'>" "</xsl:text>
      <xsl:value-of select="$doctype.system" />
      <xsl:text disable-output-escaping='yes'>"></xsl:text>

      <!-- further processing here -->
      <html>

      </html>
    </xsl:template>
</xsl:stylesheet>
查看更多
趁早两清
3楼-- · 2019-07-06 05:02

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.

查看更多
登录 后发表回答