【问题标题】:SimpleXMLIterator in PHP not traversing the XML tree in BFS-wise mannerPHP 中的 SimpleXMLIterator 不以 BFS 方式遍历 XML 树
【发布时间】:2015-11-18 03:04:49
【问题描述】:

我正在尝试在 php 版本 5.6.11 中使用 SimpleXMLIterator 以 BFS 顺序迭代 XML 树。但是,我发现它只是遍历嵌套在级别 1 的 XML 元素,就在级别 0 的根节点下方,跳过级别 2、3、...的所有嵌套元素。

那么如何让迭代器以 BFS 方式遍历 XML 树?

PHP documentation 提到迭代器应该是递归的。代码如下:

<?php

function getXMLCode() {

  $xmlCode = <<<XML
  <home>
    <livingroom>
      <sofa>
        <leftPillow></leftPillow>
        <rightPillow></rightPillow>
      </sofa>
      <television></television>
    </livingroom>
    <bedroom>
      <bed>
        <sheet></sheet>
        <duvet></duvet>
        <pillow></pillow>
      </bed>
    </bedroom>
    <bathroom>
      <sink></sink>
      <toilet></toilet>
      <bath>
        <bathtap></bathtap>
      </bath>
    </bathroom>
    <kitchen>
      <fridge>
        <lettuce>
          <snail></snail>
        </lettuce>
      </fridge>
    </kitchen>
  </home>
XML;

  return $xmlCode;

}

function test() {

  $xmlCode = getXMLCode();

  $simpleXMLIterator = new SimpleXMLIterator($xmlCode);

  foreach ($simpleXMLIterator as $xmlElement) {

    echo $xmlElement->getName(), "\n";

  }

}

test();

这里是输出,如上所述,它不构成 BFS 遍历(加上根节点也被省略了):

输出:

livingroom
bedroom
bathroom
kitchen

预期输出:

home
livingroom
bedroom
bathroom
kitchen
sofa
television
bed
sink
toilet
bath
fridge
leftPillow
rightPillow
sheet
duvet
pillow
bathtap
lettuce
snail

【问题讨论】:

    标签: php xml tree iterator


    【解决方案1】:

    使用以下内容:

    $it = new RecursiveIteratorIterator(
        new SimpleXmlIterator($xml),
        RecursiveIteratorIterator::SELF_FIRST
    );
    
    foreach ($it as $key => $value){
        print(trim($key) . PHP_EOL);
    }
    

    http://ideone.com/5udHSg

    【讨论】:

    • 您的答案仅涵盖第 2 级列出的元素,但不包括诸如 之类的第 3 级元素。您能否更新您的答案以包括 XML 元素的任意嵌套?
    • 我已经在ideone.com 上尝试过你的更新代码,但它对我不起作用。
    • 顶级总是从这些中省略,所以你永远不会得到home。如果需要,可以将其包裹得更深一层。 通常你知道顶层是什么。
    • 再试一次,我想我现在明白了。我忘记添加RecursiveIteratorIterator::SELF_FIRST 选项。我也更新了ideone。
    • 感谢您的回答,非常感谢。唯一的问题是您的遍历是 DFS 遍历(深度优先),而我正在寻找 BFS 遍历(宽度优先),并将其发布在单独的答案中。
    【解决方案2】:

    following code 使用 SimpleXMLIterator 遍历 XML 树 BFS 样式,这是最初提出的问题。不幸的是,由于 SimpleXMLElement 的设计方式,似乎无法使用 SimpleXMLIterator 输出根元素。

    <?php
    
    function getXMLCode() {
    
      $xmlCode = <<<XML
      <home>
        <livingroom>
          <sofa>
            <leftPillow></leftPillow>
            <rightPillow></rightPillow>
          </sofa>
          <television></television>
        </livingroom>
        <bedroom>
          <bed>
            <sheet></sheet>
            <duvet></duvet>
            <pillow></pillow>
          </bed>
        </bedroom>
        <bathroom>
          <sink></sink>
          <toilet></toilet>
          <bath>
            <bathtap></bathtap>
          </bath>
        </bathroom>
        <kitchen>
          <fridge>
            <lettuce>
              <snail></snail>
            </lettuce>
          </fridge>
        </kitchen>
      </home>
    XML;
    
      return $xmlCode;
    
    }
    
    function test() {
    
      $xmlCode = getXMLCode();
    
      $currentSimpleXMLIterator = new SimpleXMLIterator($xmlCode);
    
      $nonTraversedSimpleXMLIterators = array($currentSimpleXMLIterator);
    
      while (count($nonTraversedSimpleXMLIterators) > 0) {
    
        $currentSimpleXMLIterator = array_shift($nonTraversedSimpleXMLIterators);
    
        for ($currentSimpleXMLIterator->rewind(); $currentSimpleXMLIterator->valid(); $currentSimpleXMLIterator->next()) {
    
          if ($currentSimpleXMLIterator->hasChildren()) {
    
            $childSimpleXMLIterator = $currentSimpleXMLIterator->getChildren();
    
            array_push($nonTraversedSimpleXMLIterators, $childSimpleXMLIterator);
    
          }
    
          echo $currentSimpleXMLIterator->current()->getName(), "\n";
    
        }
    
      }
    
    }
    
    test();
    

    输出:

    livingroom
    bedroom
    bathroom
    kitchen
    sofa
    television
    bed
    sink
    toilet
    bath
    fridge
    leftPillow
    rightPillow
    sheet
    duvet
    pillow
    bathtap
    lettuce
    snail
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 1970-01-01
      • 1970-01-01
      • 2016-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多