我正在尝试使用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>
template.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似乎从title元素中删除了命名空间。我也不明白为什么将html命名空间添加到head元素。
答案 0 :(得分: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>
答案 1 :(得分:1)
http://www.w3.org/1999/xhtml
命名空间用于XHTML。因此,您应该将输出模式设置为xml
而不是html
,并为XHTML输出正确的doctype,或者将其呈现为html
,而不使用任何命名空间。
请注意,XSLT不太适合生成HTML5,但如果您注意细节(例如哪些元素必须为空等等),则它非常适合生成HTML 4或XHTML。
答案 2 :(得分:0)
我无法解释或重现您的结果。
首先,带有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处理器中存在错误。