【问题标题】:PHP XMLREADER Nested ElementsPHP XMLREADER 嵌套元素
【发布时间】:2014-07-09 07:29:05
【问题描述】:

您好,我正在尝试使用 XML Reader 读取一些我不知道元素名称的动态 xml。我需要使用 XML Reader 而不是 SimpleXML,因为这就是我的服务器上可用的全部内容。 我遇到的麻烦是试图拥有可以处理嵌套和非嵌套元素的东西。 我的 XML 看起来像

<status>
  <state>active</state>
  <time>2014-07-15T04:00:00.000Z</time>
    <output-type>archive</output-type>
   <sources>
<source>
<class>audio</class>
<channels>
    <channel>
        <position>left</position>
        <average>0</average>
        <peak>0</peak>
    </channel>
    <channel>
        <position>right</position>
        <average>1095</average>
        <peak>1114</peak>
    </channel>
</channels>
</source>
</status>

但也可能看起来像:

<status>inactive</status>

我正在使用以下代码:

    while ($reader->read()) {
        if ($reader->nodeType == XMLReader::ELEMENT) {
            $element = $reader->name;
            //$elementarray[] = $element;
            echo $element;
            if ($reader->depth <1){echo"</br>";}
        }

        if ($reader->nodeType == XMLReader::TEXT) {
            $value = $reader->value;
            $valuearray[] = $value;
            echo " : ".$value."</br>";                 
        }
    }

这个输出

1stElement2ndelement : text

无论如何我都无法在文档记录不佳的 XML 阅读器中找到输出

1stElement:
2ndelement: text

我可以用它来填充一个数组。

感谢任何帮助,因为我是 PHP 新手。

【问题讨论】:

    标签: php xml xmlreader


    【解决方案1】:

    不要发布伪 xml。这是无效的 xml(元素名称不能以数字开头)。它使您难以理解/验证您的问题。 DOM 可用吗?只有 XMLReader 而没有 DOM 会很奇怪。有了 DOM,你就有了 Xpath,而且它更容易使用。

    所以让我们假设一些选项 xml。

    $xml = <<<'XML'
    <options>
      <one>1</one>
      <two>2</two>
    </options>
    XML;
    

    XML 阅读器将读取每个节点。记住最后一个元素节点的名称。如果找到文本节点且不为空,则将具有记住名称的内容添加到结果数组中。

    $reader = new XMLReader();
    $reader->open('data:/text/plain,'.urlencode($xml));
    
    $result = [];
    $element = null;
    while ($reader->read()) {
      switch ($reader->nodeType) {
      case XMLReader::ELEMENT :
        $element = $reader->name;
        break;
      case XMLReader::TEXT :
        $value = $reader->value;
        if (trim($value) != '') {
          $result[$element] = $value;
        }
        break;
      }
    }
    
    var_dump($result);
    

    输出:

    array(2) {
      ["one"]=>
      string(1) "1"
      ["two"]=>
      string(1) "2"
    }
    

    在 DOM 中,可以只选择元素节点到列表中并对其进行迭代:

    $dom = new DOMDocument();
    $dom->loadXml($xml);
    $xpath = new DOMXpath($dom);
    
    $result = [];
    foreach ($xpath->evaluate('/options/*') as $node) {
      $result[$node->localName] = $node->nodeValue;
    }
    
    var_dump($result);
    

    演示:https://eval.in/170803

    DOMXpath::evaluate() 允许您使表达式相对于上下文节点并获取标量。因此,您通常会获取可以迭代的标量或节点列表。结果取决于 Xpath 表达式,因此您将始终知道。

    $dom = new DOMDocument();
    $dom->loadXml($xml);
    $xpath = new DOMXpath($dom);
    
    foreach ($xpath->evaluate('//channels/channel') as $channel) {
      var_dump(
        $xpath->evaluate('string(position)', $channel),
        $xpath->evaluate('number(1095)', $channel),
        $xpath->evaluate('number(1114)', $channel)
      );
    }
    

    演示:https://eval.in/172551

    【讨论】:

    • 谢谢,我没有考虑过 DOM,但它要简单得多。我已按照建议更新了 xml。我在重复节点(例如“通道”)时遇到问题,任何建议都将不胜感激。
    • 您需要迭代它们,就像我在示例中使用选项子项所做的那样。检查评估()的第二个参数,它是上下文。您可以使用它来使您的表达式相对于节点。我将在答案中添加一个示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 2017-05-24
    • 1970-01-01
    • 2014-07-07
    相关资源
    最近更新 更多