【问题标题】:XML Parsing - PHP encodingXML 解析 - PHP 编码
【发布时间】:2014-10-12 00:23:09
【问题描述】:

我有一个很大的 XML (>15Mb),我必须读取它、解析它并将一些值存储在数据库中。我的问题是,XML 有不同的格式(UTF-8、ISO-8859-1)。

使用 UTF-8 没有问题。但是 ISO-8859-1 给我带来了巨大的问题!!标签带有特殊字符,XMLReader 和 readOuterXML() 无法正确解析

已经尝试过,但没有成功

$xml = new XMLReader;
$xml->open($import_file,'ISO-8859-1');  

试过了:

  • utf8_encode
  • mb_convert_encoding($stringXML, 'UTF-8' );
  • iconv("ISO-8859-1", "UTF-8//TRANSLIT", $stringXML);

XML(简体)

  • 标签(id)-->没问题
  • 标签 (baños) --> 问题

xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
    <id><![CDATA[5531]]></id>
    <baños><![CDATA[0]]></baños>
</data>

他们都没有帮助我。

【问题讨论】:

  • 向我们展示实际的 xml 数据。尝试复制粘贴它,然后将无法解析的实际字符的十六进制转储。这将有助于确定问题。
  • @Evert XML 已上传!谢谢
  • 好的,这是重要的一点!在命令行(或其他十六进制编辑器)上使用hex-dump -C 并找出用于ñ 字符的字节值。我们要确保它实际上是 ISO-8859-1,而不是别的什么。
  • @Evert 我得到了这个答案 。我的 ñ 被一个“。”改变了
  • hexdump 会自动将任何非 ascii 字符更改为 .。重要的部分在该行的前半部分,即实际代码。在那里你的ñ 变成了0x96。 0x96 在 ISO-8859-1 中不是有效的字符代码,在 CP-1252 中也不是。所以无论你的编码是什么,它都是别的东西!

标签: php html xml encoding utf-8


【解决方案1】:

你在 php 中的内部编码是什么?您可以通过echo mb_internal_encoding();查看。

如果是 UTF-8,那么mb_convert_encoding($data, "UTF-8") 不会做任何事情,因为第三个参数$from_encoding 已经是“UTF-8”了。

您必须提供源编码作为函数的第三个参数。

所以也许这可以解决问题:

//check which encoding the data has? 
$encoding = mb_detect_encoding($data);
if($encoding != "UTF-8"){
    //specify from which encoding to convert to utf-8
    $data = mb_convert_encoding($data, "UTF-8", $encoding); 
}

【讨论】:

  • mb_detect_encoding 的问题在于它不支持 MacRoman(此 XML 文件的实际编码)。支持的编码的完整列表可以在here找到。
  • @Tip-Sy,谢谢你的提示,我不知道这一点。所以如果它应该在纯 php 中完成,看起来你必须自己实现它。看起来这是一个示例实现:ctd-web.fr/blog/2011/02/18/…
【解决方案2】:

我能够使用 Symfony 的 XmlEncoder 类 (https://github.com/symfony/Serializer) 成功解码给定的 xml。我将 xml 存储在 test.xml 文件中以保证正确的编码(因为我的 php 文件默认以 UTF-8 编码)。

$encoder = new Symfony\Component\Serializer\Encoder\XmlEncoder();
$data = $encoder->decode(file_get_contents('test.xml'), 'xml');
//$data = ['id' = 5531, 'baños' => 0]

【讨论】:

    【解决方案3】:

    如果 XML 标签中的特殊字符有问题,这里有一种在解析前清理标签的快速肮脏方法:

    $xml = <<<END
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <data>
        <id><![CDATA[5531]]></id>
        <baños><![CDATA[0]]></baños>
    </data>
    END;
    
    function FilterXML($matches)
    {
      return $matches[1] . preg_replace('/[^a-z]/ui', '_', $matches[2]) .
        $matches[3];
    }
    
    var_dump(preg_replace_callback('#(</?)([^!?]+?)(\\s|>)#', 'FilterXML', $xml));
    

    它将用&lt;ba_os&gt;替换&lt;baños&gt;

    【讨论】:

      【解决方案4】:

      正如@Evert 指出的,你的ñ 的字节码是:0x96,而你的XML 文件的编码实际上是MacRomansee the table here)。

      如果您想将数据转换为 UTF-8 格式,您需要执行以下操作:

      $stringXML = file_get_contents('yourFile.xml');
      $data = iconv('MACINTOSH', 'UTF-8', $stringXML);
      

      另一种可能是使用 iconv 作为命令行:

      iconv -f MACINTOSH -t UTF-8 file.xml > outputUTF8.xml
      

      (这里是 Linux 库的链接:http://www.gnu.org/software/libiconv/

      【讨论】:

      • 它将 转换为
      • 如何获取 XML 文档的内容?您应该使用fopen 而不是XMLReader
      • 或者干脆使用file_get_contents(见我编辑的答案)。效果更好吗?
      • 我使用@file_get_contents('myurl/file.xml');得到它。
      • 我必须在 php 服务器中使用它
      【解决方案5】:

      您可以尝试先读取XML文件,然后转换特殊字符,再使用XMLReader读取XML字符串。

      代码如下:

      <?php
      header("Content-Type: text/plain; charset=ISO-8859-1");
      function normalizeChars($s){
          $replace = array(
              '&amp;' => 'and', '@' => 'at', '©' => 'c', '®' => 'r', 'À' => 'a',
              'Á' => 'a', 'Â' => 'a', 'Ä' => 'a', 'Å' => 'a', 'Æ' => 'ae','Ç' => 'c',
              'È' => 'e', 'É' => 'e', 'Ë' => 'e', 'Ì' => 'i', 'Í' => 'i', 'Î' => 'i',
              'Ï' => 'i', 'Ò' => 'o', 'Ó' => 'o', 'Ô' => 'o', 'Õ' => 'o', 'Ö' => 'o',
              'Ø' => 'o', 'Ù' => 'u', 'Ú' => 'u', 'Û' => 'u', 'Ü' => 'u', 'Ý' => 'y',
              'ß' => 'ss','à' => 'a', 'á' => 'a', 'â' => 'a', 'ä' => 'a', 'å' => 'a',
              'æ' => 'ae','ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e',
              'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ò' => 'o', 'ó' => 'o',
              'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ø' => 'o', 'ù' => 'u', 'ú' => 'u',
              'û' => 'u', 'ü' => 'u', 'ý' => 'y', 'þ' => 'p', 'ÿ' => 'y', 'Ā' => 'a',
              'ā' => 'a', 'Ă' => 'a', 'ă' => 'a', 'Ą' => 'a', 'ą' => 'a', 'Ć' => 'c',
              'ć' => 'c', 'Ĉ' => 'c', 'ĉ' => 'c', 'Ċ' => 'c', 'ċ' => 'c', 'Č' => 'c',
              'č' => 'c', 'Ď' => 'd', 'ď' => 'd', 'Đ' => 'd', 'đ' => 'd', 'Ē' => 'e',
              'ē' => 'e', 'Ĕ' => 'e', 'ĕ' => 'e', 'Ė' => 'e', 'ė' => 'e', 'Ę' => 'e',
              'ę' => 'e', 'Ě' => 'e', 'ě' => 'e', 'Ĝ' => 'g', 'ĝ' => 'g', 'Ğ' => 'g',
              'ğ' => 'g', 'Ġ' => 'g', 'ġ' => 'g', 'Ģ' => 'g', 'ģ' => 'g', 'Ĥ' => 'h',
              'ĥ' => 'h', 'Ħ' => 'h', 'ħ' => 'h', 'Ĩ' => 'i', 'ĩ' => 'i', 'Ī' => 'i',
              'ī' => 'i', 'Ĭ' => 'i', 'ĭ' => 'i', 'Į' => 'i', 'į' => 'i', 'İ' => 'i',
              'ı' => 'i', 'IJ' => 'ij','ij' => 'ij','Ĵ' => 'j', 'ĵ' => 'j', 'Ķ' => 'k',
              'ķ' => 'k', 'ĸ' => 'k', 'Ĺ' => 'l', 'ĺ' => 'l', 'Ļ' => 'l', 'ļ' => 'l',
              'Ľ' => 'l', 'ľ' => 'l', 'Ŀ' => 'l', 'ŀ' => 'l', 'Ł' => 'l', 'ł' => 'l',
              'Ń' => 'n', 'ń' => 'n', 'Ņ' => 'n', 'ņ' => 'n', 'Ň' => 'n', 'ň' => 'n',
              'ʼn' => 'n', 'Ŋ' => 'n', 'ŋ' => 'n', 'Ō' => 'o', 'ō' => 'o', 'Ŏ' => 'o',
              'ŏ' => 'o', 'Ő' => 'o', 'ő' => 'o', 'Œ' => 'oe','œ' => 'oe','Ŕ' => 'r',
              'ŕ' => 'r', 'Ŗ' => 'r', 'ŗ' => 'r', 'Ř' => 'r', 'ř' => 'r', 'Ś' => 's',
              'ś' => 's', 'Ŝ' => 's', 'ŝ' => 's', 'Ş' => 's', 'ş' => 's', 'Š' => 's',
              'š' => 's', 'Ţ' => 't', 'ţ' => 't', 'Ť' => 't', 'ť' => 't', 'Ŧ' => 't',
              'ŧ' => 't', 'Ũ' => 'u', 'ũ' => 'u', 'Ū' => 'u', 'ū' => 'u', 'Ŭ' => 'u',
              'ŭ' => 'u', 'Ů' => 'u', 'ů' => 'u', 'Ű' => 'u', 'ű' => 'u', 'Ų' => 'u',
              'ų' => 'u', 'Ŵ' => 'w', 'ŵ' => 'w', 'Ŷ' => 'y', 'ŷ' => 'y', 'Ÿ' => 'y',
              'Ź' => 'z', 'ź' => 'z', 'Ż' => 'z', 'ż' => 'z', 'Ž' => 'z', 'ž' => 'z',
              'ſ' => 'z', 'Ə' => 'e', 'ƒ' => 'f', 'Ơ' => 'o', 'ơ' => 'o', 'Ư' => 'u',
              'ư' => 'u', 'Ǎ' => 'a', 'ǎ' => 'a', 'Ǐ' => 'i', 'ǐ' => 'i', 'Ǒ' => 'o',
              'ǒ' => 'o', 'Ǔ' => 'u', 'ǔ' => 'u', 'Ǖ' => 'u', 'ǖ' => 'u', 'Ǘ' => 'u',
              'ǘ' => 'u', 'Ǚ' => 'u', 'ǚ' => 'u', 'Ǜ' => 'u', 'ǜ' => 'u', 'Ǻ' => 'a',
              'ǻ' => 'a', 'Ǽ' => 'ae','ǽ' => 'ae','Ǿ' => 'o', 'ǿ' => 'o', 'ə' => 'e',
              'Ё' => 'jo','Є' => 'e', 'І' => 'i', 'Ї' => 'i', 'А' => 'a', 'Б' => 'b',
              'В' => 'v', 'Г' => 'g', 'Д' => 'd', 'Е' => 'e', 'Ж' => 'zh','З' => 'z',
              'И' => 'i', 'Й' => 'j', 'К' => 'k', 'Л' => 'l', 'М' => 'm', 'Н' => 'n',
              'О' => 'o', 'П' => 'p', 'Р' => 'r', 'С' => 's', 'Т' => 't', 'У' => 'u',
              'Ф' => 'f', 'Х' => 'h', 'Ц' => 'c', 'Ч' => 'ch','Ш' => 'sh','Щ' => 'sch',
              'Ъ' => '-', 'Ы' => 'y', 'Ь' => '-', 'Э' => 'je','Ю' => 'ju','Я' => 'ja',
              'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e',
              'ж' => 'zh','з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l',
              'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's',
              'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', 'ч' => 'ch',
              'ш' => 'sh','щ' => 'sch','ъ' => '-','ы' => 'y', 'ь' => '-', 'э' => 'je',
              'ю' => 'ju','я' => 'ja','ё' => 'jo','є' => 'e', 'і' => 'i', 'ї' => 'i',
              'Ґ' => 'g', 'ґ' => 'g', 'א' => 'a', 'ב' => 'b', 'ג' => 'g', 'ד' => 'd',
              'ה' => 'h', 'ו' => 'v', 'ז' => 'z', 'ח' => 'h', 'ט' => 't', 'י' => 'i',
              'ך' => 'k', 'כ' => 'k', 'ל' => 'l', 'ם' => 'm', 'מ' => 'm', 'ן' => 'n',
              'נ' => 'n', 'ס' => 's', 'ע' => 'e', 'ף' => 'p', 'פ' => 'p', 'ץ' => 'C',
              'צ' => 'c', 'ק' => 'q', 'ר' => 'r', 'ש' => 'w', 'ת' => 't', '™' => 'tm',
              'ñ' => 'n',
          );
          return strtr($s, $replace);
      }
      
      $path_to_file = '';
      $xml_text = @file_get_contents($path_to_file);
      if(!empty($xml_text)){
          $xml_text = normalizeChars($xml_text);
          $xml = new XMLReader();
          $xml->XML($xml_text);
      }
      ?>
      

      另一方面,如果您正在寻找性能,那么您应该尝试 SimpleXML 和 DOM Document,如以下 StackOverflow 问题中所述:https://stackoverflow.com/a/1835324/1337185

      编辑:

      我添加了header("Content-Type: text/plain; charset=ISO-8859-1"),因为strtr 仅适用于 ISO-8859-1。 我使用 OP 提供的 XML 字符串进行了尝试,它运行良好。如果有任何缺失的字符,请随时将其添加到数组中。

      【讨论】:

      • 我已经这样做了:但不替换字符... $content = @file_get_contents("www.path.com/file.xml"); $content = $this->normalizeChars($content); echo "替换完成!
        "; $newxml = simplexml_load_string($content); print_r($newxml);
      • 我很高兴它成功了。如果您认为它解决了您的问题,请对答案投票。
      • 不.. @Wissam El-Kik 我写了“不替换字符”。它没有解决我的问题。
      • @user2855036 我刚刚意识到strtr 需要一个字符集 ISO-8859-1。现在它应该可以工作了。
      • 这是一种在解析之前修改源代码的技巧,通常不能解决底层编码问题。您应该使用 iconv 而不是试图重新发明轮子。为什么'ת'应该映射到't'而不是'n'?如果你这样做,就没有语义。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 2012-11-07
      • 2020-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多