php - 如何将 Amazon MWS 响应中的 UTF-8 转义字符串转换为正确的 UTF-8?

标签 php mongodb utf-8 simplexml amazon-mws

在 XML Amazon MWS ListOrders 响应的一部分中,我们在一个元素中得到了转义的 UTF-8 字符:

<Address><Name>Ram&#xC3;&#xAD;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&#xC3;&#xAD;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&#xC3;&#xAD;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/

相关文章:

PHP OOP 和 AJAX : How to handle serverside in Class?

php - 在 php/mysql 中检测结果集的结尾

php - 尝试使用ajax删除mysql数据库条目

javascript - Mongoose 无法从 MongoDB 数据库获取数据

node.js - Mongoose - this.find() 不存在

xml - 如何在 Perl 中将 XML 文档从 Latin-1 转换为 UTF-8?

python-2.7 - 获取适当长度的表情符号

php - 在开始 Web 项目之前,我应该采取哪些步骤来描述架构?

mongodb - WiredTiger和就地更新

r - 在 R 中读取 XML 时编码丢失