问题 - 仅在文档​​开头允许XML声明

时间:2011-03-29 22:08:55

标签: php xml xmlreader

xml:19558:解析器错误:仅在文档开头允许XML声明

任何解决方案?我正在使用php XMLReader来解析一个大的XML文件,但是收到了这个错误。我知道文件格式不正确但我认为不可能通过该文件并删除这些额外的声明。所以任何想法,请帮助

4 个答案:

答案 0 :(得分:20)

确保第一个标签前没有任何空格。 试试这个:

    <?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文件有多好。告诉我,如果没有。

编辑: 这是另一个解决方案,它应该更好地使用更大的文件(在读取文件时解析)。

<?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 :(得分:1)

如果您有多个XML声明,则可能会有许多XML文件以及多个根元素的串联。目前尚不清楚你将如何有意义地解析它们。

非常努力地获取XML的来源,首先为您提供真正的XML。如果这不起作用,请查看在解析XML之前是否可以进行一些预处理以修复XML。

答案 2 :(得分:1)

此问题的另一个可能原因是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中打开文件即可看到这些字节。

答案 3 :(得分:0)

是php Storm的一个bug 如果你使用 phpstorm ,phpstorm 会让你的代码从第二行开始(不管你做什么)!所以你应该去你的主机并通过直接管理员或 cpanel 编辑器编辑你的文件,然后把你的

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

代码在第一行, “希望能帮到你”