如何使用PHP使用UTF-16编码生成有效的XML文件

时间:2013-03-04 12:02:57

标签: php xml character-encoding domdocument utf-16

我正在尝试使用PHP生成UTF-16编码的XML文件,但是当我打开生成的文件时出现问题。 我使用DOMDocument来创建文件。 使用UTF-8编码,没问题。 使用Notepad ++打开XML文件时,它看起来像这样:

<?xml version="1.0" encoding="UTF-16"?>਍㰀伀䈀㸀ഀ
<CLIENT>਍    㰀䈀伀䴀㸀ഀ
  <BO>਍        㰀䄀搀洀䤀渀昀漀㸀ഀ
      <Object>2</Object>਍          㰀嘀攀爀猀椀漀渀㸀㈀㰀⼀嘀攀爀猀椀漀渀㸀ഀ
    </AdmInfo>਍        㰀䈀甀猀椀渀攀猀猀倀愀爀琀渀攀爀猀㸀ഀ
      <row>਍   

         㰀䌀愀爀搀吀礀瀀攀㸀㠀㰀⼀䌀愀爀搀吀礀瀀攀㸀ഀ

... 等等 !!! 有人能帮帮我吗?

使用Notepad ++,我将编码设置为UTF-8而不使用BOM,文件如下:

 <?xml version="1.0" encoding="UTF-16"?>਍㰀伀䈀㸀ഀ
  <CLIENT>਍    㰀䈀伀䴀㸀ഀ
      <BO>਍        㰀䄀搀洀䤀渀昀漀㸀ഀ
          <Object>2</Object>਍          㰀嘀攀爀猀椀漀渀㸀㈀㰀⼀嘀攀爀猀椀漀渀㸀ഀ
        </AdmInfo>਍        㰀䈀甀猀椀渀攀猀猀倀愀爀琀渀攀爀猀㸀ഀ
          <row>਍            㰀䌀愀爀搀吀礀瀀攀㸀㠀㰀⼀䌀愀爀搀吀礀瀀攀㸀ഀ
            <CardCode>01000001</CardCode>਍          㰀⼀爀漀眀㸀ഀ
        </BusinessPartners>਍      㰀⼀䈀伀㸀ഀ
    </BOM>਍  㰀⼀䌀䰀䤀䔀一吀㸀ഀ

作为请求的PHP文件的一部分:

    header('Content-Type: text/xml');
                    //header('Content-Transfer-Encoding: binary');
                    $xml = new DOMDocument();
                    $xml->version='1.0';
                    $xml->encoding='UTF-16';
                    $ob_client = $xml->createElement('OB');
                        $client_element = $xml->createElement('CLIENT');
                            $client_bom_element = $xml->createElement('BOM');
                                $client_bo_element = $xml->createElement('BO');
                                    $client_adminfo_element = $xml->createElement('AdmInfo');
                                        $client_adminfo_object_element = $xml->createElement('Object', '2');
                                        $client_adminfo_version_element = $xml->createElement('Version', '2');

                                    $client_BusinessPartners_element = $xml->createElement('BusinessPartners');
                                        $client_BusinessPartners_row_element = $xml->createElement('row');
                                            $client_BusinessPartners_row_cardtype_element = $xml->createElement('CardType', $_XML_CardType);
                                            $client_BusinessPartners_row_cardcode_element = $xml->createElement('CardCode', $_XML_CardCode);

...
$xml->formatOutput = true;                  
                    echo $xml->saveXML();
                    $xml->save('rudy-xml-particulier'.$commandeId.'.xml');

非常感谢。

1 个答案:

答案 0 :(得分:2)

您已经使用UTF-16生成XML文件。您需要做的就是预先指定编码:

$doc = new DOMDocument();
$doc->encoding='UTF-16';

因此,添加数据(尤其是元素值)时更有可能出现问题。 PHP不会发出任何警告,也不会阻止您添加非UTF-8字节序列。这是一个引发偶数的例子:

$_XML_CardType = "\xA9"; # non utf-8 byte-sequence (latin-1 copyright symbol)
$xml->createElement('CardType', $_XML_CardType); # returns DOMElement

然后当你使用

echo $xml->saveXML();

PHP可能会告诉您该问题(取决于PHP版本,错误报告设置和底层库)和(对于较新的PHP版本)在发生错误的位置切断字符串。示例性错误消息是:

  

警告:DOMDocument :: saveXML():输出转换因转换错误而失败,字节为0xA9 0x3C 0x2F 0x69

因此,您需要做的就是确保您使用createElement作为值的字符串数据是UTF-8编码的。这就是你需要做的所有事情。

正如您所说,从数据库中获取数据,请参阅PHP数据库客户端库的文档,了解如何以UTF-8编码返回字符串。这应该立即解决你的问题。

为了确保您在插入之前获得UTF-8编码的字符串测试,例如使用Regex to detect Invalid UTF-8 String

if (!preg_match('//u', $_XML_CardType) {
    throw new Exception("Non utf-8 string deteced.");
}
$xml->createElement('CardType', $_XML_CardType);

这将抛出异常,而不是插入。同样log/display errors并按照错误流来发现其他问题。