XSLT不一致地呈现HTML br标签

时间:2015-10-06 05:43:46

标签: html xslt xhtml itext

在应用呈现html的XSL时,我观察到不一致的行为。我的具体问题是在下面的代码块之后。

XML实例:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <element1>
        <child2>XXXXXX</child2>
    </element1>
</root>

我的简单XSLT

<?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"/>

  <xsl:template match="/">
  <html  xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title>Test Instance</title>
      </head>   
      <body>
        <xsl:value-of select="/root/element1/child2"/>
        <br/>
        NBSP = '&#160;'
        <br/>
        <xsl:apply-templates select="//element1"/>
      </body>
  </html>
  </xsl:template>    

  <xsl:template match="//element1">
      Call From Template:
      <br/>
      <xsl:value-of select="./child2"/>
      <br/>
  </xsl:template>
</xsl:stylesheet>

我的结果输出

<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <title>Test Instance</title>
   </head>
   <body>XXXXXX<br></br>
                NBSP = '&nbsp;'
                <br></br>
            Call From Template:
            <br xmlns="">XXXXXX<br xmlns=""></body>
</html>

所以我的两个具体问题如下:

  1. 根模板呈现的'br'标记始终如一 在渲染输出中关闭,而从应用变换渲染的那些不是。我对它应该呈现的方式的理解是所有'br'标签都将保持打开状态。 任何人都可以解释为什么会发生这种情况吗?如果我使用saxon 9.0.3.5将输出方法更改为'xhtml'或使用任何其他解析器将'xml'更改为'xml',它会通过关闭所有解析器来一致地呈现'br'标记他们。
  2. 我的第二个问题涉及到插入到html输出中的非阻塞空间()的处理。当渲染为输出并使用默认的UTF-8编码时,它会使用&amp; nbsp; 显式显示非中断空格,而将输出指定为xhtml或xml会导致空间呈现为C2 A0 ,这是非破坏空间的UTF-8表示。有什么想法为什么它将它呈现为xhtml的UTF-8而不是html?虽然我猜这是因为xhtml应该解析的方式与html,我发现某些xhtml解析器(特别是iText XMLWorker)没有正确解码表示为UTF-8的非中断空间代码,我正在试图弄清楚如何解决它。
  3. 由于

2 个答案:

答案 0 :(得分:0)

XSLT 2.0,html输出

<xsl:transform
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

<xsl:output method="html" version="5" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="/">
  <html>
      <head>
        <title>Test Instance</title>
      </head>   
      <body>
        <xsl:value-of select="/root/element1/child2" />
        <br/>
        NBSP = '&#160;'
        <br/>
        <xsl:apply-templates select="//element1" />
      </body>
  </html>
</xsl:template>

<xsl:template match="//element1">
  Call From Template:
  <br />
  <xsl:value-of select="./child2" />
  <br />
</xsl:template>

</xsl:transform>

XSLT 2.0,xhtml输出,强制&amp; nbsp; (不是个好主意)

<xsl:transform
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

<xsl:output method="xhtml" encoding="UTF-8" indent="yes" use-character-maps="a" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:character-map name="a">
  <xsl:output-character character="&#160;" string="&amp;nbsp;"/>
</xsl:character-map>

<xsl:template match="/">
  <html>
      <head>
        <title>Test Instance</title>
      </head>   
      <body>
        <xsl:value-of select="/root/element1/child2" />
        <br/>
        NBSP = '&#160;'
        <br/>
        <xsl:apply-templates select="//element1" />
      </body>
  </html>
</xsl:template>

<xsl:template match="//element1">
  Call From Template:
  <br />
  <xsl:value-of select="./child2" />
  <br />
</xsl:template>

</xsl:transform>

XSLT 2.0,xhtml输出,正确方法

<xsl:transform
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

<xsl:output method="xhtml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="/">
  <html>
      <head>
        <title>Test Instance</title>
      </head>   
      <body>
        <xsl:value-of select="/root/element1/child2" />
        <br/>
        NBSP = '&#160;'
        <br/>
        <xsl:apply-templates select="//element1" />
      </body>
  </html>
</xsl:template>

<xsl:template match="//element1">
  Call From Template:
  <br />
  <xsl:value-of select="./child2" />
  <br />
</xsl:template>

</xsl:transform>

XSLT 1.0,xhtml输出

<xsl:transform
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/xhtml"
    version="1.0">

<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="/">
  <html>
      <head>
        <title>Test Instance</title>
      </head>   
      <body>
        <xsl:value-of select="/root/element1/child2" />
        <br/>
        NBSP = '&#160;'
        <br/>
        <xsl:apply-templates select="//element1" />
      </body>
  </html>
</xsl:template>

<xsl:template match="//element1">
  Call From Template:
  <br />
  <xsl:value-of select="./child2" />
  <br />
</xsl:template>

</xsl:transform>

答案 1 :(得分:0)

With the HTML output method, a br element is treated specially (rendered as <br>) only if it is in no namespace.

With the XHTML output method, a br element is treated specially (rendered as <br />) only if it is in the XHTML namespace.

This changes with XSLT 3.0 which supports method="html" version="5", where "no namespace" and "XHTML namespace" are both accepted.