如何sanitize/validate XML 文件在PHP?数据错误
How to sanitize/validate XML file in PHP? PCDATA error
我收到了我无法控制的 XML 个文件,我需要从中提取数据。这是我的代码:
public function importXML($filePath)
{
$dom = new \DOMDocument();
$dom->load($filePath);
$xml = simplexml_import_dom($dom);
foreach ($xml->PLU as $item) {
$name = $item->NAME;
我在某处读到 DOMDocument() 清理了 xml 的一部分,因此最好先将文件加载到那里,然后他们通过 simplexml_import_dom() 导入它。截至目前,此代码在 70% 的时间内有效,我成功地完成了所有我想做的事情,但另外 30% 的时间我收到此错误:
[ExceptionError] DOMDocument::load(): PCDATA invalid char Value 31 in /path/to/file.xml, line 2
我已经对这个问题进行了一些挖掘,并且找到了一个可能的解决方案,但就我而言,它没有:
第一个选项:
function utf8_for_xml($string)
{
return preg_replace ('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $string);
}
但是我尝试在 simplexml_import_dom() 之前将我的 $dom 加载文件放入其中,但它给出了相同的错误。
第二个选项:
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)))
{
$ret .= chr($current);
}
else
{
$ret .= " ";
}
}
return $ret;
}
我也没有运气,因为错误继续发生。 XML 文件编码是 "WINDOWS-1251",如果有帮助,一些文件使用西里尔文。
是编码问题还是与 XML 文件(开始和结束标记等)的有效性有关?
如有任何帮助,我们将不胜感激。
感谢@NigelRen,我做了以下并且效果很好:
private function stripInvalidXml($value)
{
$ret = "";
$current;
if (empty($value))
{
return $ret;
}
$length = strlen($value);
for ($i=0; $i < $length; $i++)
{
// For >PHP7.3 use ord($value[$i])
$current = ord($value{$i});
if (($current == 0x9) ||
($current == 0xA) ||
($current == 0xD) ||
(($current >= 0x20) && ($current <= 0xD7FF)) ||
(($current >= 0xE000) && ($current <= 0xFFFD)) ||
(($current >= 0x10000) && ($current <= 0x10FFFF)))
{
$ret .= chr($current);
}
else
{
$ret .= " ";
}
}
return $ret;
}
我使用了我发现的第二种验证方法加上用 file_get_contents 打开 xml 然后修改它:
public function importXML($filePath)
{
$content = file_get_contents($filePath);
$modified = $this->stripInvalidXml($content);
$dom = new \DOMDocument();
$dom->loadXML($modified);
$xml = simplexml_import_dom($dom);
现在 $xml 有效,您可以根据需要进行处理。
我收到了我无法控制的 XML 个文件,我需要从中提取数据。这是我的代码:
public function importXML($filePath)
{
$dom = new \DOMDocument();
$dom->load($filePath);
$xml = simplexml_import_dom($dom);
foreach ($xml->PLU as $item) {
$name = $item->NAME;
我在某处读到 DOMDocument() 清理了 xml 的一部分,因此最好先将文件加载到那里,然后他们通过 simplexml_import_dom() 导入它。截至目前,此代码在 70% 的时间内有效,我成功地完成了所有我想做的事情,但另外 30% 的时间我收到此错误:
[ExceptionError] DOMDocument::load(): PCDATA invalid char Value 31 in /path/to/file.xml, line 2
我已经对这个问题进行了一些挖掘,并且找到了一个可能的解决方案,但就我而言,它没有:
第一个选项:
function utf8_for_xml($string)
{
return preg_replace ('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $string);
}
但是我尝试在 simplexml_import_dom() 之前将我的 $dom 加载文件放入其中,但它给出了相同的错误。
第二个选项:
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)))
{
$ret .= chr($current);
}
else
{
$ret .= " ";
}
}
return $ret;
}
我也没有运气,因为错误继续发生。 XML 文件编码是 "WINDOWS-1251",如果有帮助,一些文件使用西里尔文。
是编码问题还是与 XML 文件(开始和结束标记等)的有效性有关?
如有任何帮助,我们将不胜感激。
感谢@NigelRen,我做了以下并且效果很好:
private function stripInvalidXml($value)
{
$ret = "";
$current;
if (empty($value))
{
return $ret;
}
$length = strlen($value);
for ($i=0; $i < $length; $i++)
{
// For >PHP7.3 use ord($value[$i])
$current = ord($value{$i});
if (($current == 0x9) ||
($current == 0xA) ||
($current == 0xD) ||
(($current >= 0x20) && ($current <= 0xD7FF)) ||
(($current >= 0xE000) && ($current <= 0xFFFD)) ||
(($current >= 0x10000) && ($current <= 0x10FFFF)))
{
$ret .= chr($current);
}
else
{
$ret .= " ";
}
}
return $ret;
}
我使用了我发现的第二种验证方法加上用 file_get_contents 打开 xml 然后修改它:
public function importXML($filePath)
{
$content = file_get_contents($filePath);
$modified = $this->stripInvalidXml($content);
$dom = new \DOMDocument();
$dom->loadXML($modified);
$xml = simplexml_import_dom($dom);
现在 $xml 有效,您可以根据需要进行处理。