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

时间:2018-05-27 16:15:23

标签: php xml xml-namespaces

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

这是我所看到的一个精简的例子。

MY-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中正确解析第一个文档的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

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

$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
  "
}

这将输出子节点,而不必使用命名空间。