首页 > 解决方案 > 当我尝试使用 XSLT 输出方法“html”时,为什么我的 SVG 不显示?

问题描述

如果这是一个简单的问题,我深表歉意,因为我在 XSLT 上还是个新手。我遇到了一个问题,如果我的输出方法设置为 html,我在 XSLT 中生成的 SVG 图像将不会显示。如果我打开所需的 xml 文件,对其进行转换并在浏览器 (IE v11) 中查看它,则整个文档都会加载,但 SVG 图像本身除外。在 IE 中,如果我右键单击文档并选择“查看源代码”,我可以看到 SVG 信息就在那里,就在它预期的位置。

如果我将输出方法设置为 xml 并在 IE 中打开,则会出现 SVG 图像但文档结构不存在(但重申一下:目标是以 html 格式输出,因为它在其他进程中使用)

下面是一小段简单的测试 XSLT 和从“查看源代码”看到的转换后 xml(省略不相关的内容)。在我处理更大的图片之前,我试图让这个工作在小范围内发挥作用。

还要注意的是,svg:text 标签确实显示了提到的文本,尽管它看起来更像是一个简单的文本条目而不是图像的一部分。

对于熟悉它的人来说,大部分功能来自 RenderX 的 XSLT 条形码生成器。

XSLT:

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

  <xsl:import href="code128.xsl"/>

  <xsl:output method='html' media-type="image/svg" encoding='UTF-8' indent='yes'/>

  <xsl:template match="/">
    <html lang="en">
      <head>
        <title>SVG bar code examples</title>
      </head>
      <body>
        <h1>SVG bar code examples</h1>
        <ul>
          <xsl:apply-templates select="//barcode"/>
        </ul>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="barcode">
    <li>
      <xsl:call-template name="barcode-code128">
      .
      <!--Parameters here-->
      .
      </xsl:call-template>
    </li>
  </xsl:template>
</xsl:stylesheet>

转换后 XML:

<?xml version="1.0" encoding="utf-8"?>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">
  <head>
    <title>SVG bar code examples</title>
  </head>
  <body>
    <h1>SVG bar code examples</h1>
    <ul>
      <li>
        <svg:svg width="29.494444444444443mm" height="12.7mm" viewBox="0 0 10618 4572">
          <svg:path d="M 686 686 l 0 2286 138 0 0 -2286 z m ..."(truncated due to length)>
          <svg:text x="6068" y="4420" text-anchor="middle" font-family=...
        </svg:svg>
      </li>
      .
      <!--More SVG images here-->
      .
    </ul>
  </body>
</html>

标签: xsltsvg

解决方案


如果您想使用输出方法html,那么您应该使用 HTML 语法,并且 HTML 4 和 HTML5 或简称为 HTML 现在都不支持名称空间,特别是不支持前缀元素名称。因此,要在 text/html 中识别您的 SVG 元素,您只需svgpath并且text作为没有任何前缀的元素名称,唯一允许的“命名空间”声明将xmlns="http://www.w3.org/2000/svg"svg元素上。

我也不确定 IE 的 SVG 支持,也许它只在符合标准的渲染模式下启用,这意味着,因为它method="html"应该设置旧浏览器区分怪癖模式和标准兼容模式到后一种模式.<xsl:output method="html" indent="yes" version="5" doctype-system="about:legacy-doctype"/>doctype-system

如果您使用的库创建了前缀元素,那么您将需要通过额外的转换步骤运行它们以去除命名空间前缀,在单个转换中,在 XSLT 1 中只能使用专有扩展函数将结果树片段转换为节点集:

  <xsl:template match="barcode">
    <li>
      <xsl:variable name="barcode-rtf">
      <xsl:call-template name="barcode-code128">
      .
      <!--Parameters here-->
      .
      </xsl:call-template>
      </xsl:variable>
      <xsl:apply-templates select="msxml:node-set($barcode-rtf)/node()" xmlns:msxml="urn:schemas-microsoft-com:xslt" mode="strip-svg-prefix"/>
    </li>
  </xsl:template>


  <xsl:template match="@* | node()" mode="strip-svg-prefix">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()" mode="strip-svg-prefix"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="svg:*" mode="strip-svg-prefix" xmlns:svg="http://www.w3.org/2000/svg">
    <xsl:element name="{local-name()}" namespace="http://www.w3.org/2000/svg">
      <xsl:apply-templates select="@* | node()" mode="strip-svg-prefix"/>
    </xsl:copy>
  </xsl:template>

请注意,对于 text/html 和 HTML 4 或 HTML5 作为转换目标method="html",我建议对 HTML 元素完全不使用命名空间,即删除您拥有的 XHTML 命名空间声明。否则空元素的序列化可能不会给出正确的 HTML 语法。


推荐阅读