【问题标题】:xslt transforms utf-8 characters to a different encodingxslt 将 utf-8 字符转换为不同的编码
【发布时间】:2016-03-27 12:09:13
【问题描述】:

这个问题是间歇性出现的,就是我做了很多xslt转换都没有这个问题,然后在我最近一次xslt转换的时候突然出现了。

我有大量的html输入文件,结构类似于下面的a.html:

<html>
  <body>
    <div class="wrd">
      <div class="wrd-id">5</div>
      <div class="wrd-wrd">address</div>
      <div class="wrd-ipa">əˈdres,ˈaˌdres</div>
    </div>
    <div class="a">...</div>
  </body>
</html>

当我检查输入文件的编码时,我得到以下结果:

file -I a.html 
a.html: text/html; charset=utf-8

我使用类似于以下 a.xslt 的 xslt 转换 html 文件:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
 <xsl:output omit-xml-declaration="yes" indent="yes" encoding="UTF-8" />
 <xsl:strip-space elements="*" />

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

 <xsl:template match="div[@class='a']" >
  <xsl:apply-templates select="*|node()" />
 </xsl:template>

</xsl:stylesheet>

我使用的脚本类似于下面的a.sh:

#!/bin/bash
xsltproc --html a.xslt a.html > b.html

更完整的 bash 脚本如下:

#!/bin/bash
xsltproc --html a.xslt a.html \
| hxnormalize -x -l 1024 \
| sed '/^$/d' \
> b.html

我得到以下结果b.html:

<html>
  <body>
    <div class="wrd">
      <div class="wrd-id">5</div>
      <div class="wrd-wrd">address</div>
      <div class="wrd-ipa">ÉËdres,ËaËdres</div>
    </div>
    ...
  </body>
</html>

事实上,我的输出包含一些我无法在此处复制和粘贴的倒置问号。请看下图

属于 UTF-8 字符集的输入字符已转换为其他字符。

当我检查文件 b.html 的编码时,我得到以下结果:

file -I b.html
b.html: text/html; charset=utf-8

如何防止 xslt 转换将我的字符从一种编码更改为另一种编码?

更新 1

通过从 xsltproc 命令中删除选项“--html”,问题得到解决。但是我仍然不确定为什么。

#!/bin/bash
xsltproc a.xslt a.html > b.html

更新 2

输入文件似乎被解释为 ASCII 或 ISO-8859-1 而不是 UTF-8。我在输入 a.html 中插入了以下标题:

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="content-type" content="text/html">
  </head>

但是输出 b.html 还是一样的。

更新 3

我已将 a.xslt 更新为以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes" />
 <xsl:strip-space elements="*"/>

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

</xsl:stylesheet>

请注意不同的 xsl:output 行

这会创建具有相同问题的 b.html,但第一行给出了以下 html 声明:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">

也许后面有使用 ASCII 或 ISO-8859-1 来解释输入文件的原因。

【问题讨论】:

    标签: xslt


    【解决方案1】:

    解决方案

    xsltproc 从 META Content-Type 标头中获取 HTML 输入文件的文件编码。当这样的标头不存在时,它可能会假定文件编码不正确并在读取文件时破坏文件。

    我在输入 a.html 中插入了以下标头:

    <head>
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    </head>
    

    我已经运行了以下 bash 脚本:

    #!/bin/bash
    xsltproc --html a.xslt a.html > b.html
    

    xslt a.xslt 如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes" />
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="@* | node()">
      <xsl:copy>
       <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
     </xsl:template>
    
    </xsl:stylesheet>
    

    输出文件 b.html 终于如期而至:

    <html>
      <body>
        <div class="wrd">
          <div class="wrd-id">5</div>
          <div class="wrd-wrd">address</div>
          <div class="wrd-ipa">əˈdres,ˈaˌdres</div>
        </div>
        <div class="a">...</div>
      </body>
    </html>
    

    【讨论】:

    • 谢谢。一个非常有帮助的答案。
    • 其实我已经发现有--encoding参数允许你指定输入文件的编码,如果元信息不存在于html文件中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    相关资源
    最近更新 更多