Проблема: XML-декларация разрешена только в начале документа

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

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


person Aamir    schedule 29.03.2011    source источник
comment
Если он неправильно сформирован, это не XML. Если это не XML, то XMLReader не будет хорошо работать.   -  person drudge    schedule 30.03.2011
comment
единственная проблема с файлом - это несколько объявлений :( (‹?xml version=1.0 encoding=UTF-8 standalone=no?›) в любом случае?   -  person Aamir    schedule 30.03.2011
comment
Нужно удалить пробелы! Вот видео, как обнаружить и исправить такие ошибки: youtube.com/watch?v=4jWhO07ICvw   -  person Juri Fab    schedule 28.11.2016


Ответы (4)


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

    <?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
}
?>
person Ben    schedule 29.03.2011
comment
нет, дорогой, это не так. на самом деле эта строка (‹?xml версия=1.0 кодировка=UTF-8 standalone=no?›) повторяется в файле много раз.. это то, что говорится в отчете об ошибке. - person Aamir; 30.03.2011
comment
у вас есть ‹xml несколько раз? Должен быть только один раз (это корневой тег, например html) - person Ben; 30.03.2011
comment
да, но это уже несколько раз, как решить проблему? что-то вроде удаления этих лишних тегов, но как??? - person Aamir; 30.03.2011
comment
Вы можете разбить строку на каждое вхождение ‹xml, а затем проанализировать каждый из них отдельно - person Ben; 30.03.2011
comment
это хорошая идея, но как дорогая? :( - person Aamir; 30.03.2011
comment
я новичок в этом, понятия не имею, как это сделать, пожалуйста, помогите мне - person Aamir; 30.03.2011
comment
Попробуйте это: $split = preg_split('/(?<=<xml)(?!$)/', $string); print_r($split); - person Ben; 30.03.2011
comment
позвольте мне опубликовать мой код здесь, а затем дайте мне знать, где использовать этот код в этом. - person Aamir; 30.03.2011
comment
$reader = новый XMLReader(); $reader-›open('data.xml') или die(Файл не найден); while($reader-›read()) { switch($reader-›nodeType) { case константа('XMLREADER::ELEMENT'): if ($reader-›name == 'record') { $dataa= $reader -›readInnerXml(); } Перерыв; } $reader-›close(); - person Aamir; 30.03.2011
comment
хм... это хорошо, но у меня есть файл, а не строка :( пожалуйста, дайте мне знать, как заменить эту строку именем файла. - person Aamir; 30.03.2011
comment
большое спасибо, дорогая, теперь позвольте мне подтвердить, что первая часть собирается делать? поскольку я храню XML-файл, а не текст, и он очень большой по размеру, будет ли это работать для этого? - person Aamir; 30.03.2011
comment
Я могу добавить комментарии к каждой части, если хотите. Дай мне минуту. - person Ben; 30.03.2011
comment
пробуя это, позвольте мне проверить, будет ли это работать для этого или нет, но, похоже, это не работает для этого большого файла :( - person Aamir; 30.03.2011
comment
но независимо от того, работает это или нет, я очень благодарен за ваше время. спасибо действительно много. - person Aamir; 30.03.2011
comment
Я думаю, вы могли бы разобрать его, пока вы его прокручивали (кстати, анализ 4 ГБ займет много времени, подумайте о set_time_limit (0), чтобы исправить это). - person Ben; 30.03.2011
comment
Попробуйте тот, который я только что выложил. Должен работать с новым файлом, если нет, дайте мне код ошибки - person Ben; 30.03.2011

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

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

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

person kaven    schedule 31.03.2014

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

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

person Ned Batchelder    schedule 29.03.2011
comment
хм .. не могли бы вы дать мне знать, как удалить эти лишние декларации? любой простой php-код? на самом деле я очень новичок во всем этом и просто застрял здесь. - person Aamir; 30.03.2011
comment
я не понимаю, что ты имеешь в виду...! Постарайтесь сначала получить источник XML, чтобы получить настоящий XML. - person Aamir; 30.03.2011
comment
Откуда вы берете XML? Не могли бы вы поговорить с лицом, ответственным за создание XML, потому что это неправильно и должно быть исправлено. Чтобы исправить XML, посмотрите замену строки PHP. - person Ned Batchelder; 30.03.2011
comment
Дайте нам весь документ xml и анализатор php, который у вас есть. Тогда мы можем помочь еще немного - person Ben; 30.03.2011
comment
@ mazzzzz хорошо, но как я могу предоставить вам файл, его размер около 4 ГБ :( - person Aamir; 30.03.2011
comment
@ Нед Бэтчелдер прямо сейчас я не могу ничего сделать, например попросить людей исправить файл :( Замена строки PHP? - person Aamir; 30.03.2011
comment
Вау, зачем тебе 4-гигабайтный xml-файл. Похоже, я бы использовал базу данных для такого размера данных. Вы можете попробовать str_split, но размер строк может быть больше, чем может обработать php. Я согласен с AAmir, поговорите с людьми, которые создают xml. - person Ben; 30.03.2011
comment
дорогой, это набор данных, который я хочу вставить в базу данных... :( - person Aamir; 30.03.2011

Это ошибка php Storm. Если вы используете php storm, php storm заставляет ваш код начинаться со второй строки (независимо от того, что вы делаете)! Таким образом, вы должны пойти на свой хост и отредактировать свой файл с помощью прямого администратора или редактора cpanel и поместить свой

   <?xml version=“1.0” encoding=“UTF-8” ?>

Код в первой строке, «надеюсь, это поможет»

person Arian Fm    schedule 22.06.2021