簡體   English   中英

如何清理/驗證 PHP 中的 XML 文件? PCDATA 錯誤

[英]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);
}

但是我嘗試將 $dom 加載的文件放在 simplexml_import_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”,如果有幫助,某些文件使用 Cyrilic。

是編碼問題還是與 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 是有效的,您可以根據需要進行處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM