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

Sah*_*nda 4 php xml

我有一个包含多个声明的 xml 文件,如下所示

<?xml version="1.0" encoding="UTF-8"?>
<root>
 <node>
  <element1>Stefan</element1>
  <element2>42</element2>
  <element3>Shirt</element3>
  <element4>3000</element4>  
</node>
</root>

<?xml version="1.0" encoding="UTF-8"?>
<root>
 <node>
  <element1>Damon</element1>
  <element2>32</element2>
  <element3>Jeans</element3>
  <element4>4000</element4>  
</node>
</root>
Run Code Online (Sandbox Code Playgroud)

当我尝试加载 xml 时

$data = simplexml_load_file("testdoc.xml") or die("Error: Cannot create object");
Run Code Online (Sandbox Code Playgroud)

然后它给了我以下错误

Warning: simplexml_load_file(): testdoc.xml:11: parser error : XML declaration allowed only at the start of the document in C:\xampp\htdocs\crea\services\testxml.php on line 3

Warning: simplexml_load_file(): <?xml version="1.0" encoding="UTF-8"?> in C:\xampp\htdocs\crea\services\testxml.php on line 3

Warning: simplexml_load_file(): ^ in C:\xampp\htdocs\crea\services\testxml.php on line 3

Warning: simplexml_load_file(): testdoc.xml:12: parser error : Extra content at the end of the document in C:\xampp\htdocs\crea\services\testxml.php on line 3

Warning: simplexml_load_file(): <root> in C:\xampp\htdocs\crea\services\testxml.php on line 3

Warning: simplexml_load_file(): ^ in C:\xampp\htdocs\crea\services\testxml.php on line 3
Error: Cannot create object
Run Code Online (Sandbox Code Playgroud)

请让我知道如何解析此 xml 或如何将其拆分为多个 xml 文件,以便我可以阅读。文件大小约为 1 GB。

col*_*sar 7

第二行

<?xml version="1.0" encoding="UTF-8"?>
Run Code Online (Sandbox Code Playgroud)

需要删除。任何文件中只允许有 1 个 xml 声明,并且它必须是第一行。

严格来说,您还需要有一个根元素(尽管我见过宽松的解析器)。只需用伪标签包装内容,这样你的文件就会看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<metaroot><!-- synthetic unique root, no semantics attached -->
    <root>
        <!-- ... -->
    </root>
    <root>
        <!-- ... -->
    </root>

    <!-- ... -->
</metaroot>
Run Code Online (Sandbox Code Playgroud)

(非常)大文件的解决方案:

使用sed消除问题的XML声明,并printf添加一个XML声明加上独特的根元素。一系列 bash 命令如下:

  printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<metaroot>\n" >out.xml
  sed '/<\?xml /d' in.xml >>out.xml
  printf "\n</metaroot>\n" >>out.xml
Run Code Online (Sandbox Code Playgroud)

in.xml表示您的原始文件,out.xml即清除结果。

printf打印单个 xml 声明和开始/结束标记。 sed是一种逐行编辑文件的工具,根据正则表达式模式匹配执行操作。要匹配的模式是 xml 声明 ( <\? xml)的开头,要执行的操作是删除该行。

笔记:

  • 命令中的反斜杠在它们出现的位置转义具有特殊语义的符号。
  • sed 也可用于 windows/macos。

替代解决方案

另一种选择是将文件拆分为单个格式良好的文件(取自此 SO 答案

csplit -z -f 'temp' -b 'out%03d.xml' in.xml '/<\?xml /' {*}
Run Code Online (Sandbox Code Playgroud)

它生成名为out000.xml, out001.xml, ... 的文件,您应该至少知道已处理到输入文件中的单个文件数量的大小,以确保自动编号的安全(尽管您当然可以获取输入文件的字节数作为幅度,-b 'out%09d.xml'在上述命令中使用)。