我有一个PHP脚本,用于导入和解析XML文件并将数据保存到数据库中:
utf8_general_ci
,charset:utf8
utf-8
ANSI
,包含智能引号(来自MS Word)因此,在导入期间,我会先将XML文件中的文本utf8_encode()
保存到数据库中,然后再显示在页面上。
但成功导入后,保存到DB中,
?
个字符(从CMD查看)即使使用utf8_encode()
,有关为什么智能引号未正确转换的任何想法?
修改
@Tomalak:XML文件实际上是.txt
,没有XML声明(<?xml ... ?>
),也没有根元素。我的脚本实际上添加了一个根元素,以便解析器工作:
utf8_encode('<article>' . file_get_contents($xmlfile) . '</article>');
好像我需要添加一个XML声明..?如果是这样,它应该是什么样的?
答案 0 :(得分:6)
如果您的XML字符串(即文件内容)不编码为UTF-8,则需要一个表示文件编码的XML声明。如果缺少XML声明,解析器将采用UTF-8。
只要您不使用“特殊”字符(即ASCII范围之外的任何字符),即使您的文件不是真正 UTF-8编码,它也可以在没有声明的情况下工作。这是因为UTF-8与ASCII字节兼容。但是,只要在其中一个代码页上使用了字符 - 比如“智能引号” - 它就会中断,因为它们由UTF-8中的不同字节表示。
在您的情况下,遗留编码中有一些文本文件,您可以使用根元素进行包装,以将它们转换为格式良好的XML。因此,您需要自己添加XML声明:
'<?xml encoding="Windows-1252"?><article>'.file_get_contents($xmlfile).'</article>'
这样,您可以指示DOMDocument
如何解释字符串中的字节。我假设你Windows-1252
,因为你说ANSI并提到了引号。
事实上,95%的时间这是人们真正的意思,即使在Linux上,即使他们说ISO-8859-1
(或latin-1
),这几乎是,但不是 同样的事情。
要确保您可以在十六进制编辑器中打开文本文件,找到一些特殊字符并将其字节值与可疑编码进行比较。对于Windows-1252
。对于卷曲引号,预期的字节值为:
“
147(0x93)”
148(0x94)一旦声明了字符串中各个字节的含义,DOMDocument
就可以理解它们并做正确的事。
当涉及到数据库时,我强烈怀疑存在一些自动编码转换。我承认我对PHP / mySQL / Unicode集成的了解还不够清楚。
答案 1 :(得分:1)
正在正确转换它们,因为utf8_encode正是它应该做的事情,并将它们从输入流中删除。
utf8_encode将ISO-8859-1中的文本转换为UTF-8编码。 ISO-8859-1不包含smartquote字符。您的网页可能在浏览器中被视为MSWIN1252编码,其中包含智能引用字符,并且您通过在其上调用utf8_encode强制PHP输入ISO-8859-1。这意味着将进入数据库的唯一字符是这些字符:http://en.wikipedia.org/wiki/ISO/IEC_8859-1#Codepage_layout
要解决此问题,您必须确保网页本身采用UTF-8编码,并从代码中删除所有utf8_encode / utf8_decode语句。本页介绍了如何正确使用UTF-8:http://malevolent.com/weblog/archive/2007/03/12/unicode-utf8-php-mysql/
答案 2 :(得分:0)
是的,问题是有两种类型的智能引号。
windows-1252 和 latin-1
utf8_encode 假设它是 latin-1,所以它的智能引号是错误的。
如果我们知道输入的数据是windows-1252,我们可以使用iconv进行转换。
$string=iconv ( "Windows-1252" , "UTF-8" , $oldstring );
这才是真正的答案。