为什么 SimpleXMLElement 无法找到 XML 文件的内容?

Why is SimpleXMLElement not able to find contents of XML file?

我需要使用 php 解析从第三方收到的 xml 文档。我无法要求文档的维护者修复其结构。当我使用 simplexml_load_file 解析文档时,XML 文档是空的。

这是我所看到的精简示例。

我的-file.xml:

<?xml version="1.0" encoding="utf-8"?>
<DataSet>
  <diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    aaa
  </diffgr:diffgram>
</DataSet>

我是这样处理的(从命令行):

php > $xml = simplexml_load_file('my-file.xml');
php > print_r($xml);
SimpleXMLElement Object
(
)

我期待 xml 结构通过 print_r 显示。

事实上,当我删除命名空间声明时,一切似乎都正常(尽管有一些预期的 XML 解析警告):

我的文件-nonamespace.xml:

<?xml version="1.0" encoding="utf-8"?>
<DataSet>
  <diffgr:diffgram>
    aaa
  </diffgr:diffgram>
</DataSet>

在命令行上以相同的方式处理它(删除警告):

php > $xml = simplexml_load_file('my-file-nonamespace.xml');

// a bunch of xml parse warnings
php > print_r($xml);
SimpleXMLElement Object
(
    [diffgr:diffgram] =>
    aaa

)

因此,问题与无效的命名空间声明有关。我可能可以在文件上使用正则表达式在解析之前删除名称空间声明,但这不是我想要的方向。

正确解析 PHP 中第一个文档的最佳方法是什么?

问题不是数据未加载,而是子元素位于不同的命名空间。

$xml = simplexml_load_file('my-file.xml');
var_dump($xml->children("diffgr", true));

这会从当前元素的特定命名空间中选择子元素。

请注意,您应该使用 URI,因为前缀可能会改变,但这只是为了表明数据在那里。

编辑: 如果 XML 有问题,那么第一步是忽略错误,然后检查加载的内容 ...

libxml_use_internal_errors(true);
$xml = simplexml_load_file('my-file.xml');
echo $xml->asXML();

这会让您了解结果是什么状态,即使它已加载。一个简单的例子是...

libxml_use_internal_errors(true);
$xml = simplexml_load_file('my-file.xml');
echo $xml->asXML();
var_dump($xml->children());

有..

<?xml version="1.0" encoding="utf-8"?>
<DataSet>
  <diffgr:diffgram>
    aaa
  </diffgr:diffgram>
</DataSet>

请注意命名空间是如何存在的,但未声明命名空间。输出是...

<?xml version="1.0" encoding="utf-8"?>
<DataSet>
  <diffgr:diffgram>
    aaa
  </diffgr:diffgram>
</DataSet>
/home/nigel/workspace2/Test/t1.php:22:
class SimpleXMLElement#2 (1) {
  public $diffgr:diffgram =>
  string(11) "
    aaa
  "
}

这无需使用命名空间即可输出子项。