我正在撰写基于myanimelist.net REST API的Google Chrome扩展程序。有时XMLHttpRequest响应文本包含unicode。
例如:
<title>Onegai My Melody Sukkiri�</title>
如果我从文本创建一个HTML节点,它看起来像这样:
Onegai My Melody Sukkiri�
实际的标题是:
Onegai My Melody Sukkiri♪
为什么我的文字没有正确呈现,我该如何解决呢?
我认为这些是关键部分:
function htmlDecode(input){
var e = document.createElement('div');
e.innerHTML = input;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
function xmlDecode(input){
var result = input;
result = result.replace(/</g, "<");
result = result.replace(/>/g, ">");
result = result.replace(/\n/g, " ");
return htmlDecode(result);
}
此外:
var parser = new DOMParser();
var xmlText = response.value;
var doc = parser.parseFromString(xmlDecode(xmlText), "text/xml");
答案 0 :(得分:2)
<title>Onegai My Melody Sukkiri�</title>
亲爱的,亲爱的!这不仅是错误的文本,它甚至不是格式良好的XML。 acirc
和ordf
是未在XML中预定义的HTML实体,然后它们之间存在无效的UTF-8序列(一个高字节,大概是0x99)。
问题是myanimelist使用PHP函数htmlentities()
生成输出'XML'(但“如果它不是格式良好,它不是XML”)。这样不仅可以对HTML中的潜在敏感HTML字符<&"'
进行HTML转义,还可以转义所有非ASCII字符。
这会生成错误的字符,因为PHP默认将输入htmlentities()
视为ISO-8859-1而不是UTF-8,这是他们实际使用的编码。但是开始时这是错误的,因为XML实体集在XML中不存在。他们真正想要使用的是htmlspecialchars()
,它只留下非ASCII字符,只能逃避真正敏感的字符。因为那些在XML中是敏感的,htmlspecialchars()
对于XML也适用于HTML。
htmlentities()
几乎总是错误的事情;通常应该使用htmlspecialchars()
代替。当您定位纯ASCII输出时,您可能希望将非ASCII字节编码为实体引用的位置。但即便如此htmlentities()
也会失败,因为它没有为没有预定义实体名称的字符进行字符引用(&#...;
)。很没用。
无论如何,你无法真正从中恢复受损的数据。 �
表示XMLHttpRequest为UTF-8-undecodable的字节序列,因此信息不可挽回地丢失。你必须说服myanimelist根据上面的几段修复他们破碎的XML输出,然后才能继续。
此外,他们应该将其作为Content-Type: text/xml
而不是text/html
返回。然后你可以直接从XMLHttpRequest对象中获取responseXML
,而不是弄乱DOMParsers。
答案 1 :(得分:1)
所以,我在工作中发现了类似的类似的内容,我做了一些研究来证实我的假设。
如果您查看上面发布的返回值,您会注意到告诉实体“â”。 99%的情况下,当您看到此实体时,如果意味着您有字符编码问题(通常将UTF-8字符编码为ISO-8859-1)。
我要测试的第一件事是在API返回中强制使用字符编码。 (这是一个很长的镜头,但你可以看看)
其次,我会尝试对返回的数据强制执行字符编码(我知道有一个.htaccess覆盖,但我不知道Chrome扩展中允许什么,所以你必须研究它。)
我相信的是,当您使用数据创建节点时,您没有在文档上设置字符编码,并且浏览器(通常根据我的经验)默认为ISO-8859-1。因此,请检查以确保问题不是您的文档。
最后,如果您找不到字符编码的来源(或无法阻止它),您将必须编写一个会话表来替换您所获得的格式错误的值与您想要的{ JS'“replace”应该没问题(http://www.w3schools.com/jsref/jsref_replace.asp)}。
答案 2 :(得分:-1)
您不能只使用简单的搜索和替换来修复编码问题,因为它们是unicode,而不是键盘上键入的字符。
如果您计划通过AJAX检索数据,则必须以UTF-8格式将数据存储在服务器上。此问题可能是由于某人粘贴了使用完全不同的编码方案(ISO-8859)的MS-Word中的字符。
如果你无法修复数据,那你就有点不知所措了。
有关详细信息,请参阅:UTF-8 vs. Unicode