XML中存在非法字符。

3
我有一个PHP文件,它根据从多个来源导入的数据生成Xml网站地图。由于导入数据中一行存在非法字符,我的网站地图目前不规范,但我无法删除它。
该字符看起来代表“平方”或上标2,并表示为正方形。我尝试将其粘贴到十六进制编辑器中,但它显示为“?”,十六进制代码也对应“?”。我还尝试使用iconv将所有源编码转换为所有目标编码,但没有任何组合可以删除此字符。
我还有以下函数以删除非ASCII字符:
function stripInvalidXml($value)
{
    $ret = "";
    $current;
    if (empty($value)) 
    {
        return $ret;
    }

    $length = strlen($value);
    for ($i=0; $i < $length; $i++)
    {
        $current = ord($value{$i});
        if (($current == 0x9) ||
            ($current == 0xA) ||
            ($current == 0xD) ||
            (($current >= 0x20) && ($current <= 0xD7FF)) ||
            (($current >= 0xE000) && ($current <= 0xFFFD)) ||
            (($current >= 0x10000) && ($current <= 0x10FFFF)))
        {
            if($current != 0x1F)
            {
                $ret .= chr($current);
            }
        }
        else
        {
            $ret .= " ";
        }
    }


    return $ret;
}

然而,这仍然没有将其删除。如果我逐步执行代码,则非法字符会在Eclipse的调试窗口中扩展为￿。它遇到问题的字符串如下所示(希望它可以正确粘贴):
251gm-50
有没有什么函数可以删除此字符并防止出现此问题,任何建议都将不胜感激 - 我对导入的数据几乎没有控制权,因此需要在Xml生成点完成。
编辑:
发布后,我可以看到该字符未正确显示。在Eclipse窗口中查看时,它显示为&#65535;(无空格 - 如果我留下空格,则呈现字符,看起来像￿)。
3个回答

3

您正在尝试执行字符转码。不要自己操作,使用PHP库。

我发现iconv非常有用:

$cleanText = iconv('UTF-8','ISO-8859-1//TRANSLIT//IGNORE', $srcText);

这段代码将从utf-8转换为iso-8859,尝试重新映射“奇异”的字符,并忽略无法转码的字符。

我只是猜测源编码是utf-8。您需要发现传入数据使用的编码,并在XML头中声明要进行的转换。

一个Linux命令行工具可以猜测文件的编码,名为enca


我尝试了使用所有输入和输出编码的组合,使用iconv进行转换,但没有任何一种方式起作用。 - Macros
我将编码从UTF-8更改为ISO-8859-1,这解决了我的盒子中的4f问题。 - webdad3

2

这是错误的:

    $current = ord($value{$i});
    if (($current == 0x9) ||
        ($current == 0xA) ||
        ($current == 0xD) ||
        (($current >= 0x20) && ($current <= 0xD7FF)) ||
        (($current >= 0xE000) && ($current <= 0xFFFD)) ||
        (($current >= 0x10000) && ($current <= 0x10FFFF)))
    {
        if($current != 0x1F)
            $ret .= chr($current);
    }

ord()函数以字节为单位工作,因此永远不会返回大于0xFF的任何内容。

我猜测你的XML文件无效,因为文件包含无效的UTF-8序列(确实,即￿,即0xFFFF,在UTF-8中是无效的)。这可能来自复制粘贴不同编码的不同XML文件。

我建议你使用DOM扩展来处理XML混合,它通过在内部转换编码为UTF-8来自动处理不同的编码。


好的建议 - 我继承了一些生成Xml字符串的代码,使用DOM会更加清晰简洁。 - Macros
DOM 可能对于生成像 RSS 订阅源这样的内容来说有些过度:他可能不需要所有的操作/搜索功能,并且对于大型文档,DOM 结构的内存占用可能过高。 - Iacopo
1
@lacopo 过度杀伤?在哪方面?对于操作XML,DOM是PHP拥有的最佳库。如果内存是一个问题,那么可以使用XMLWriter。在这两种情况下,结果比使用字符串连接或重新发明这些库已经自己完成的所有操作更可靠。 - Gordon

1

我认为我一开始走了错误的方向 - 不是编码问题,而是字符是表示“平方”符号的HTML实体。由于URL中的描述仅用于搜索引擎目的,因此我可以使用以下正则表达式安全地删除所有htmlentities:

$content = preg_replace("/&#?[a-z0-9]+;/i","",$content);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接