xml: 19558: ошибка парсера: объявление XML разрешено только в начале документа
любые решения? Я использую php XMLReader для синтаксического анализа большого XML-файла, но получаю эту ошибку. Я знаю, что файл не хорошо отформатирован, но я думаю, что его невозможно просмотреть в файле и удалить эти дополнительные объявления. так что любая идея, ПОЖАЛУЙСТА, ПОМОГИТЕ
Убедитесь, что перед первым тегом не осталось пробелов. Попробуй это:
<?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 в нужный файл. Примечание. Я не знаю, как хорошо это работает для файла 4gb. Скажите, если это не так.
EDIT: Вот еще одно решение, оно должно работать лучше с большим файлом (анализирует, поскольку он читает файл).
<?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 } ?>
Если у вас несколько объявлений XML, у вас, вероятно, есть конкатенация многих файлов XML, а также более одного корневого элемента. Неясно, как вы осмысленно разбираете их.
Постарайтесь, чтобы источник XML стал первым источником XML. Если это не сработает, посмотрите, можете ли вы выполнить предварительную обработку, чтобы исправить XML, прежде чем разбирать его.
Другой возможной причиной этой проблемы является файловая система unicode. Если кодировка вашего XML – UTF-8, содержимое файла всегда начинается с этих 3 байтов «EF BB BF». Эти байты могут быть интерпретированы неправильно, если вы пытаетесь преобразовать из байтового массива в строку. Решение состоит в том, чтобы написать массив байтов напрямую, без чтения getString из массива байтов.
ASCII не имеет файловой головки Unicode: FF FE UTF-8: EF BB BF UTF-32: FF FE 00 00
Просто откройте файл в ultraedit, и вы можете увидеть эти байты.