我正在使用xslt样式表转换混合的html和xml文档,并仅提取html元素。
源文件:
<?xml version="1.0" encoding="utf-8" ?>
<html >
<head>
<title>Simplified Example Form</title>
</head>
<body>
<TLA:document xmlns:TLA="http://www.TLA.com">
<TLA:contexts>
<TLA:context id="id_1" value=""></TLA:context>
</TLA:contexts>
<table id="table_logo" style="display:inline">
<tr>
<td height="20" align="middle">Big Title Goes Here</td>
</tr>
<tr>
<td align="center">
<img src="logo.jpg" border="0"></img>
</td>
</tr>
</table>
<TLA:page>
<TLA:question id="q_id_1">
<table id="table_id_1">
<tr>
<td>Label text goes here</td>
<td>
<input id="input_id_1" type="text"></input>
</td>
</tr>
</table>
</TLA:question>
</TLA:page>
<!-- Repeat many times -->
</TLA:document>
</body>
</html>
样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:TLA="http://www.TLA.com" exclude-result-prefixes="TLA">
<xsl:output method="html" indent="yes" version="4.0" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()" priority="-2">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- This element-only identity template prevents the
TLA namespace declaration from being copied to the output -->
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<!-- Pass processing on to child elements of TLA elements -->
<xsl:template match="TLA:*">
<xsl:apply-templates select="*" />
</xsl:template>
</xsl:stylesheet>
输出:
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Simplified Example Form</title>
</head>
<body>
<table id="table_logo" style="display:inline">
<tr>
<td height="20" align="middle">Big Title Goes Here</td>
</tr>
<tr>
<td align="center"><img src="logo.jpg" border="0"></td>
</tr>
</table>
<table id="table_id_1">
<tr>
<td>Label text goes here</td>
<td><input id="input_id_1" type="text"></td>
</tr>
</table>
</body>
</html>
然而,存在一个问题,即meta,img和input元素未正确关闭。我已将xsl:output设置为html,将版本设置为4.0,据我所知,应输出正确的html。
我猜测第一个xsl:template / xsl:copy指令需要进行细微的更改,但我的xslt技能非常有限。
需要进行哪些更改才能正确关闭代码?
P.S。我不确定不同工具/解析器之间是否存在差异,但我使用Visual Studio 2012来调试样式表,以便我可以看到任何更改的直接影响。
答案 0 :(得分:2)
我担心你不理解基于SGML的HTML 4或4.01的语法规则:空元素的正确标记是<input>
,它不是<input></input>
也不是{{ 1}}也不<input/>
。
因此,根据您对HTML输出方法和版本的请求,您可以在序列化XSLT转换的结果树时获得正确的HTML语法。
检查实例http://validator.w3.org/check?uri=http%3A%2F%2Fhome.arcor.de%2Fmartin.honnen%2Fxslt%2Ftest2013040901Result.html&charset=%28detect+automatically%29&doctype=Inline&group=0,在那里没有正确关闭的元素没有错误或警告。
然而,对于http://validator.w3.org/check?uri=http%3A%2F%2Fhome.arcor.de%2Fmartin.honnen%2Fxslt%2Ftest2013040902Result.html&charset=%28detect+automatically%29&doctype=Inline&group=0,您会收到有关元素未正确关闭的警告。
所以<input />
输出方法是正确的,另请参阅http://www.w3.org/TR/xslt#section-HTML-Output-Method说明:
html输出方法不应输出空的结束标记 元素。对于HTML 4.0,空元素是area,base,basefont, br,col,框架,hr,img,输入,isindex,链接,元和param。对于 例如,在样式表中写为
html
或<br/>
的元素 应输出为<br></br>
。
答案 1 :(得分:1)
<meta>
,<img>
和<input>
元素不需要关闭 - 它仍然是有效的HTML。
如果你想关闭它们,可以使用xml
(使用XSLT2.0,你也可以使用xhtml
,据我所知)作为输出方法并添加{{ 1}}标记自己,如果你需要它。例如:
<meta>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:TLA="http://www.TLA.com" exclude-result-prefixes="TLA">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()" priority="-2">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="head">
<xsl:copy>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- This element-only identity template prevents the
TLA namespace declaration from being copied to the output -->
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<!-- Pass processing on to child elements of TLA elements -->
<xsl:template match="TLA:*">
<xsl:apply-templates select="*" />
</xsl:template>
</xsl:stylesheet>