从XML提取HTML时关闭标签(Closing tags when extracting HTML

2019-10-17 23:42发布

我转换的混合html和使用XSLT样式表,只提取HTML元素的XML文档。

源文件:

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

但是有在元,IMG和输入元件没有被正确关闭的问题。 所以就输出HTML和版本4.0,因为我知道自己应该正确输出HTML:我已经设置了xsl。

我猜,有需要在第一个XSL了微妙的变化:模板/ XSL:复制指令,但我的XSLT技能是非常有限的。

有什么需要改变作出拿到标记来正确关闭?

PS我不知道是否有不同的工具/解析器,但我使用Visual Studio 2012来调试样式表,这样我可以看到任何变化立竿见影的效果之间的差异。

Answer 1:

<meta> <img><input>元素不需要关闭-它仍然是有效的HTML。

如果你想拥有它们关闭,你可以使用xml (与XSLT2.0你可以使用xhtml ,也一样,据我所知)作为输出方法并添加<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>

产量

<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>


Answer 2:

我怕你不明白基于SGML的HTML其HTML 4或4.01是语法规则:一个空的元素正确的标记是<input> ,它不是<input></input>也没有<input/>也不<input />

所以,你的HTML输出方法和版本的请求就可以获得正确的HTML语法当你的XSLT转换的结果树进行序列化。

检查例如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你该元件被错误地关闭的警告。

因此, html输出方法做正确的事,也看到http://www.w3.org/TR/xslt#section-HTML-Output-Method其中说:

HTML输出方法对于空元素不应该输出结束标记。 对于HTML 4.0,空元素是区域,底座,BASEFONT,BR,山口,框架,小时,IMG,输入,ISINDEX,链接元和param。 例如,一个元件写成<br/><br></br>在样式表应该是作为输出<br>



文章来源: Closing tags when extracting HTML from XML