PHP处理含双<?xml>声明的怪异XML文件求助
处理含双XML声明文件的两种自动化方案
一、自动拆分为两个独立XML文件
如果需要将文件拆分成两个独立的XML文件,可通过PHP读取文件内容后,用正则匹配第二个XML声明的位置进行拆分,代码示例如下:
// 读取目标文件内容 $xmlContent = file_get_contents('dual-xml-file.xml'); // 匹配第二个XML声明的位置(从第一个声明结束后开始查找) preg_match('/(<\?xml.*?\?>)/s', $xmlContent, $matches, PREG_OFFSET_CAPTURE, strpos($xmlContent, '?>') + 2); if (!empty($matches)) { // 拆分出两个XML内容 $firstXml = substr($xmlContent, 0, $matches[0][1]); $secondXml = substr($xmlContent, $matches[0][1]); // 保存为独立文件 file_put_contents('first-xml.xml', $firstXml); file_put_contents('second-xml.xml', $secondXml); } else { echo "未检测到第二个XML声明"; }
说明:正则中的s修饰符允许.匹配换行符,确保能正确匹配跨换行的XML声明;strpos($xmlContent, '?>') + 2确保从第一个声明结束后开始查找,避免误匹配第一个声明。
二、无需拆分,直接读取内容的替代工具
如果不需要拆分文件,可通过清理多余XML声明后,使用DOMDocument或XMLReader读取内容:
1. 使用DOMDocument清理后加载
先移除多余的XML声明,保留第一个,再加载为DOM对象(可转为SimpleXML使用):
$xmlContent = file_get_contents('dual-xml-file.xml'); // 提取第一个XML声明 preg_match('/(<\?xml.*?\?>)/s', $xmlContent, $firstDecl); // 移除所有XML声明 $cleanedContent = preg_replace('/(<\?xml.*?\?>)/s', '', $xmlContent); // 恢复第一个声明 $cleanedContent = $firstDecl[0] . $cleanedContent; // 加载并处理 $dom = new DOMDocument(); $dom->loadXML($cleanedContent); // 转为SimpleXML(如果需要) $simplexml = simplexml_import_dom($dom);
2. 使用XMLReader流式处理(适合大文件)
XMLReader支持流式读取,可分别处理两个XML文档,避免一次性加载大文件占用过多内存:
$reader = new XMLReader(); $reader->open('dual-xml-file.xml'); // 处理第一个XML文档 $firstDom = new DOMDocument(); $firstRoot = null; while ($reader->read()) { // 遇到第二个XML声明时停止处理第一个文档 if ($reader->nodeType === XMLReader::XML_DECLARATION && $firstRoot !== null) { break; } // 捕获第一个根节点并导入到DOM if ($reader->nodeType === XMLReader::ELEMENT && $firstRoot === null) { $firstRoot = $firstDom->importNode($reader->expand(), true); $firstDom->appendChild($firstRoot); } } // 处理第二个XML文档 $secondDom = new DOMDocument(); $secondRoot = null; // 跳过第二个XML声明 $reader->next(); while ($reader->read()) { if ($reader->nodeType === XMLReader::ELEMENT && $secondRoot === null) { $secondRoot = $secondDom->importNode($reader->expand(), true); $secondDom->appendChild($secondRoot); } } $reader->close(); // 转为SimpleXML使用 $firstXml = simplexml_import_dom($firstDom); $secondXml = simplexml_import_dom($secondDom);
内容的提问来源于stack exchange,提问作者Bready
相关产品推荐
相关产品推荐

