在 XML Amazon MWS ListOrders 响应的一部分中,我们在一个元素中得到了转义的 UTF-8 字符:
<Address><Name>Ramírez Jones</Name></Address>
这个名字应该是Ramírez。变音符号 í
是 UTF-8 字符 U+00ED
(字面量为 \xc3\xad
;引用 this chart)。
但是 PHP 的 SimpleXML 函数会破坏这个字符串(你可以看到,因为我只是粘贴了),将其转换为
RamÃrez Jones
进入此处的编辑器框(显然 stackoverflow 的 ASP.NET 基础与 PHP 执行相同的操作)。
现在,当这个损坏的字符串被保存到 MongoDB 中,然后从 MongoDB 中取出时,它就会变成
RamÃ-rez Jones
出于某种原因,这里插入了一个连字符,不管你信不信,如果您选择上面的粗体文本,然后将其粘贴回 StackOverflow 编辑器窗口,它只会显示为 Ramírez
(连字符神秘地消失了,至少在 OS X 10.8.5 上是这样)!
下面是一些示例代码来说明此问题:
$xml = "<Address><Name>Ramírez Jones</Name></Address>";
$elem = new SimpleXMLAddressent($xml);
$bad_string = $elem->Name;
echo mb_detect_encoding($bad_string)."\n";
echo $elem->Name->__toString()."\n";
echo iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $elem->Name->__toString());
这是上述示例代码的输出,as run on onlinephpfunction.com's sandbox :
UTF-8
RamÃrez Jones
RamA-rez Jones
如何避免这个问题?真是把事情搞砸了。
编辑:
让我补充一下,虽然 XML 中的名称应该是 Ramírez Jones,但我需要将其音译为 Ramirez Jones(去掉我)。
修订后的最终解决方案:
它与下面的正确答案不同,但这是我发现的最优雅的解决方案。只需将示例的最后一行替换为:
echo iconv('UTF-8','ASCII//TRANSLIT', html_entity_decode($xml));
这是有效的,因为“Ô
是HTML entities .
替代解决方案
奇怪的是,这也有效:
$xml = '<?xml version="1.0"?><Address><Name>Ramírez Jones</Name></Address>';
$xml= str_replace('<?xml version="1.0"?>', '<?xml version="1.0" encoding="ISO-8859-1"?>' , $xml);
$domdoc = new DOMDocument();
$domdoc->loadXML($xml);
$xml = iconv('UTF-8','ASCII//TRANSLIT',$domdoc->saveXML());
$elem = new SimpleXMLElement($xml);
echo $elem->Name;
最佳答案
它不起作用,因为它被编码了两次。字符 í
的代码为 U+00ED
,它应该在 XML 中编码为 ED;
。
您可以使用以下任一方法修复其编码:
$name = iconv('UTF-8', 'ISO-8859-1//TRANSLIT//IGNORE', $elem->Name->__toString());
或
$name = mb_convert_encoding($elem->Name->__toString(), 'ISO-8859-1', 'UTF-8');
更新:
上面建议的两种方法都可以修复编码(它们实际上将字符串的编码从 UTF-8
转换为 ISO-8859-1
,这顺便解决了问题在眼前)。
@Hazzit 提供的解决方案也有效。
这两种解决方案(以及您的代码)的真正挑战是检测是否接收到的数据以错误的方式编码,并仅在这种情况下应用这些修复程序,让代码在以下情况下正常工作:亚马逊修复了编码问题。我希望他们能做到。
以最小的信息损失去除重音
修复编码后,为了用 ASCII 子集中的类似字母替换重音字母,您必须使用 iconv()
(因为只有 iconv()
可以帮助),就像您在示例代码中所做的那样。
$nameAscii = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $name);
第二个参数的解释可以在iconv()
的文档页面中找到。 ;另请阅读用户评论。
关于php - 如何将 Amazon MWS 响应中的 UTF-8 转义字符串转换为正确的 UTF-8?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27694608/