【问题标题】:How do I get rid of incorrect xmlns attributes in HTML transformed with XSLT如何摆脱使用 XSLT 转换的 HTML 中不正确的 xmlns 属性
【发布时间】:2011-07-21 22:56:38
【问题描述】:

我正在尝试使用 xslt 转换 .html 文档。由于某种原因,生成的 html 在 head 元素上有一个额外的 xmlns 属性,而在 title 元素上有一个空的 xmlns 属性。

example.html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head><title>foo</title></head>
  <body><h1>bar</h1><img src="baz.jpg" /></body>
</html>

模板.xsl:

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

  <xsl:output doctype-system="about:legacy-compat" method="html"
     omit-xml-declaration="yes" />

  <xsl:template match="/html/head">
    <head>
      <meta name="description" content="something added to the head element"/>
      <xsl:apply-templates select="./@*|./node()" />
    </head>
  </xsl:template>

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

</xsl:stylesheet>

我一直在用 xsltproc 和 php 测试转换。

运行 xsltproc:

$ xsltproc -html template.xsl example.html 
<!DOCTYPE html SYSTEM "about:legacy-compat">
<html xmlns="http://www.w3.org/1999/xhtml">
<head xmlns="http://www.w3.org/1999/xhtml"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="description" content="something added to the head element"></meta><title xmlns="">foo</title></head><body>
<h1>bar</h1>
<img src="baz.jpg">
</body>
</html>

使用 PHP:

<?php

$xmldoc = new DomDocument ();
$xmldoc->loadHTMLFile ("example.html");

$xsldoc = new DomDocument ();
$xsldoc->load ("template.xsl");

$xslt = new XSLTProcessor();
$xslt->importStylesheet($xsldoc);

echo $xslt->transformToXML ($xmldoc);

我希望源文档中的所有元素都在 html 命名空间中,所以我不明白为什么 apply-templates 似乎从标题元素中删除了命名空间。我也不明白为什么将html命名空间添加到head元素中。

【问题讨论】:

标签: html xslt xml-namespaces


【解决方案1】:

http://www.w3.org/1999/xhtml 命名空间用于 XHTML。因此,您应该将输出模式设置为xml 而不是html,并且还应该为XHTML 输出正确的文档类型,或者改为呈现为html 并且根本不使用任何命名空间。

请注意,XSLT 不太适合生成 HTML5,但如果您注意一些细节(例如哪些元素必须或不能为空等),它非常适合生成 HTML 4 或 XHTML。

【讨论】:

  • 更改为 似乎可以解决大部分问题。我仍然在 head 元素上获得了一个额外的 xmlns 属性,但至少它包含正确的命名空间,所以必须这样做。谢谢!
【解决方案2】:

在这种特定情况下,您应该使用一种经过修改的身份转换来删除默认命名空间:

<xsl:template match="@*|node()[not(self::*)]">
  <xsl:copy/>
 </xsl:template>

 <xsl:template match="*">
  <xsl:element name="{local-name()}">
   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>

显然请确保从您的 XSLT 中删除这一行:

xmlns="http://www.w3.org/1999/xhtml"

你的最终模板:

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

    <xsl:output doctype-system="about:legacy-compat" method="html"
        omit-xml-declaration="yes" />

    <xsl:template match="/html/head">
        <head>
            <meta name="description" content="something added to the head element"/>
            <xsl:apply-templates select="./@*|./node()" />
        </head>
    </xsl:template>

    <xsl:template match="@*|node()[not(self::*)]">
        <xsl:copy/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

  • 这似乎破坏了不应获得结束标签的元素。在原始输出中,您会看到 没有结束标记,如果我使用上面的模板,我会得到 .
  • 您的“原始输出”格式不正确。如果您转换您的数据,一个工作良好的 XSLT 处理器应该关闭所有标签,即使是不需要关闭标签的 HTML 标签。您应该对我的答案中显示的输出感到高兴:)
  • 另外,从浏览器的角度来看,你的抱怨是不相关的。
  • XSLT 2.0 具有输出方法 XHTML,它会正确地发出不应自闭合的 XHTML 元素,例如 w3.org/TR/xslt-xquery-serialization/#xhtml-output
  • @Mads 我认为你错了。所有对应的 HTML 元素,在 XHTML 中必须是自闭合的。我们将通过建议的序列化获得的最终效果类似于&lt;img /&gt; 而不是&lt;img&gt;。此外,我们将在输出中添加 XHTML 约束,这不是 OP 正在搜索的内容。
【解决方案3】:

我无法解释或重现您的结果。

首先,带有 match="/html/head" 的模板不应匹配输入文档中的任何内容,因为您的 /html/head 元素位于命名空间中。

对于 Saxon,我得到的输出是这样的,我认为这是正确的:

<!DOCTYPE html
  SYSTEM "about:legacy-compat">
<html xmlns="http://www.w3.org/1999/xhtml">  
   <head>
      <title>foo</title>
   </head>   
   <body>
      <h1>bar</h1><img src="baz.jpg"></img></body>  
</html>

因此,要么您正在做的事情与您所说的不同(例如,使用与所示不同的样式表或不同的源文档),要么您正在使用的 XSLT 处理器中存在错误。

【讨论】:

  • 我也确实在样式表中设置了一个默认命名空间,那不适用于模板匹配属性中的元素吗?
猜你喜欢
  • 1970-01-01
  • 2012-08-24
  • 1970-01-01
  • 1970-01-01
  • 2015-04-12
  • 2011-05-11
  • 2011-03-23
  • 2011-09-17
  • 2011-11-24
相关资源
最近更新 更多