代码之家  ›  专栏  ›  技术社区  ›  Andrew Eisenberg

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

  •  0
  • Andrew Eisenberg  · 技术社区  · 7 年前

    我需要使用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解析警告):

    my-file-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 回复  |  直到 7 年前
        1
  •  0
  •   Nigel Ren    7 年前

    问题不在于没有加载数据,而在于子元素位于不同的命名空间中。

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

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