代码之家  ›  专栏  ›  技术社区  ›  Kirby

PHP XMLREADER嵌套元素

  •  0
  • Kirby  · 技术社区  · 10 年前

    嗨,我正在尝试使用XMLReader来读取一些我不知道元素名称的动态XML。我需要使用XMLReader,而不是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 Reader中找到输出

    1stElement:
    2ndelement: text
    

    我可以用它填充数组。

    由于我是PHP新手,任何帮助都很感谢。

    1 回复  |  直到 10 年前
        1
  •  0
  •   ThW    10 年前

    不要发布伪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