Проблема - объявление XML разрешено только в начале документа - PullRequest
4 голосов
/ 30 марта 2011

xml: 19558: ошибка синтаксического анализатора: объявление XML разрешено только в начале документа

какие-либо решения? Я использую php XMLReader для анализа большого файла XML, но получаю эту ошибку. я знаю, что файл не очень хорошо отформатирован, но я думаю, что невозможно просмотреть файл и удалить эти дополнительные объявления. так что любая идея, ПОЖАЛУЙСТА, ПОМОГИТЕ

Ответы [ 3 ]

20 голосов
/ 30 марта 2011

Убедитесь, что перед первым тегом нет пробелов.Попробуйте это:

    <?php
//Declarations
$file = "data.txt"; //The file to read from.

#Read the file
$fp = fopen($file, "r"); //Open the file
$data = ""; //Initialize variable to contain the file's content
while(!feof($fp)) //Loop through the file, read it till the end.
{
    $data .= fgets($fp, 1024); //append next kb to data
} 
fclose($fp); //Close file
#End read file
$split = preg_split('/(?<=<\/xml>)(?!$)/', $data); //Split each xml occurence into its own string

foreach ($split as $sxml) //Loop through each xml string
{
    //echo $sxml;
    $reader = new XMLReader(); //Initialize the reader
    $reader->xml($sxml) or die("File not found"); //open the current xml string
    while($reader->read()) //Read it
    {
        switch($reader->nodeType)
        {
            case constant('XMLREADER::ELEMENT'): //Read element
                if ($reader->name == 'record')
                {
                    $dataa = $reader->readInnerXml(); //get contents for <record> tag.
                    echo $dataa; //Print it to screen.
                }
            break;
        }
    }
    $reader->close(); //close reader
}
?>

Установите переменную $ file в нужный файл.Обратите внимание, я не знаю, насколько хорошо это будет работать для файла 4 ГБ.Скажите, если это не так.

РЕДАКТИРОВАТЬ: Вот еще одно решение, он должен работать лучше с большим файлом (анализирует, как он читает файл).

<?php
set_time_limit(0);
//Declarations
$file = "data.txt"; //The file to read from.

#Read the file
$fp = fopen($file, "r") or die("Couldn't Open"); //Open the file

$FoundXmlTagStep = 0;
$FoundEndXMLTagStep = 0;
$curXML = "";
$firstXMLTagRead = false;
while(!feof($fp)) //Loop through the file, read it till the end.
{
    $data = fgets($fp, 2);
    if ($FoundXmlTagStep==0 && $data == "<")
        $FoundXmlTagStep=1;
    else if ($FoundXmlTagStep==1 && $data == "x")
        $FoundXmlTagStep=2;
    else if ($FoundXmlTagStep==2 && $data == "m")
        $FoundXmlTagStep=3;
    else if ($FoundXmlTagStep==3 && $data == "l")
    {
        $FoundXmlTagStep=4;
        $firstXMLTagRead = true;
    }
    else if ($FoundXmlTagStep!=4)
        $FoundXmlTagStep=0;

    if ($FoundXmlTagStep==4)
    {
        if ($firstXMLTagRead)
        {
            $firstXMLTagRead = false;
            $curXML = "<xm";
        }
        $curXML .= $data;

        //Start trying to match end of xml
        if ($FoundEndXMLTagStep==0 && $data == "<")
            $FoundEndXMLTagStep=1;
        elseif ($FoundEndXMLTagStep==1 && $data == "/")
            $FoundEndXMLTagStep=2;
        elseif ($FoundEndXMLTagStep==2 && $data == "x")
            $FoundEndXMLTagStep=3;
        elseif ($FoundEndXMLTagStep==3 && $data == "m")
            $FoundEndXMLTagStep=4;
        elseif ($FoundEndXMLTagStep==4 && $data == "l")
            $FoundEndXMLTagStep=5;
        elseif ($FoundEndXMLTagStep==5 && $data == ">")
        {
            $FoundEndXMLTagStep=0;
            $FoundXmlTagStep=0;
            #finished Reading XML
            ParseXML ($curXML);
        }
        elseif ($FoundEndXMLTagStep!=5)
            $FoundEndXMLTagStep=0;
    }
} 
fclose($fp); //Close file
function ParseXML ($xml)
{
    //echo $sxml;
    $reader = new XMLReader(); //Initialize the reader
    $reader->xml($xml) or die("File not found"); //open the current xml string
    while($reader->read()) //Read it
    {
        switch($reader->nodeType)
        {
            case constant('XMLREADER::ELEMENT'): //Read element
                if ($reader->name == 'record')
                {
                    $dataa = $reader->readInnerXml(); //get contents for <record> tag.
                    echo $dataa; //Print it to screen.
                }
            break;
        }
    }
    $reader->close(); //close reader
}
?>
1 голос
/ 31 марта 2014

Другая возможная причина этой проблемы - заголовок файла Unicode. Если кодировкой вашего XML является UTF-8, содержимое файла всегда будет начинаться с этих 3 байтов "EF BB BF". Эти байты могут интерпретироваться неправильно, если кто-то пытается преобразовать байтовый массив в строку. Решением является запись байтового массива в файл напрямую без чтения getString из байтового массива.

ASCII не имеет заголовка файла Юникод: FF FE UTF-8: EF BB BF UTF-32: FF FE 00 00

Просто откройте файл в ultraedit, и вы увидите эти байты.

1 голос
/ 30 марта 2011

Если у вас есть несколько деклараций XML, у вас, вероятно, есть конкатенация многих файлов XML, а также нескольких корневых элементов.Непонятно, как вы могли бы осмысленно их проанализировать.

Старайтесь изо всех сил, чтобы получить источник XML, который сначала даст вам настоящий XML.Если это не сработает, посмотрите, можете ли вы выполнить некоторую предварительную обработку, чтобы исправить XML, прежде чем анализировать его.

...