【问题标题】:How do you iterate one level at a time?你如何一次迭代一个级别?
【发布时间】:2017-09-21 00:59:43
【问题描述】:

假设我有这样的东西并且无法更改:

<xml>
<element name="breakfast" type="sandwich" />
<element name="lunch">
  <complexType>
    <element name="meat" type="string" />
    <element name="vegetables" type="vegetable" />
    <element name="chips" type="boolean" />
  </complexType>
</element>
<complexType name="sandwich">
  <element name="bread" type="string" />
  <element name="cheese" type="int" />
  <element name="butter" type="boolean" />
</complexType>
<complexType name="vegetable">
  <element name="tomato" type="int" />
  <element name="lettuce" type="boolean" />
  <element name="carrot" type="boolean" />
</complexType>
<element name="dinner" type="sandwich" />
</xml>

我想要某种数组/对象,例如:

var day = {
  time: {
    breakfast: {
      bread: "string",
      cheese: "int",
      butter: "boolean"
    },
    lunch: {
      meat: "string",
      vegetables: {
        tomato: "int",
        lettuce: "boolean",
        carrot: "boolean"
      },
      chips: "boolean"
    },
    dinner: {
      bread: "string",
      cheese: "int",
      butter: "boolean"
    },
  },
  food: {
    sandwich: {
      bread: "string",
      cheese: "int",
      butter: "boolean"
    },
    vegetable: {
      tomato: "int",
      lettuce: "boolean",
      carrot: "boolean"
    },
  }
}

我不介意什么语言,PHP 或 JavaScript 会很棒,但我真的只是想看看逻辑。我确信这有一个标准模式。

目前我有一些类似的东西:

$xml = new DOMDocument();
$xml->loadXML($data);

$day = array(
  "time" => array(),
  "food" => array()
);
getLevel1($xml->childNodes[0]);

function getLevel1(DOMNode $domNode) {
  global $day;
  foreach ($domNode->childNodes as $node) {
    if ($node->nodeName == "element") {
      if ($node->hasChildNodes()) {
        $day["time"][$node->getAttribute('name')] = getLevel2($node);
      } else {
        if (isset($day["food"][$node->getAttribute('type')])) {
          $day["time"][$node->getAttribute('name')] = $day["food"][$node->getAttribute('type')];
        } else {
          $day["time"][$node->getAttribute('name')] = $node->getAttribute('type');  
        }
      }
    };
    if ($node->nodeName == "complexType") {
      if ($node->hasChildNodes()) {
        $day["food"][$node->getAttribute('name')] = getLevel2($node);
      } else {
        $day["food"][$node->getAttribute('name')] = $node->getAttribute('type');
      }
    };
  }
};

function getLevel2(DOMNode $domNode) {
  $object = array();
  foreach ($domNode->childNodes as $node) {
    if ($node->nodeName == "element") {
      $object[$node->getAttribute('name')] = $node->getAttribute('type');
    };
    if ($node->hasChildNodes()) {
      if ($node->hasAttribute('name')) {
        $object[$node->getAttribute('name')] = getLevel2($node);
      } else {
        return getLevel2($node);
      }
    }
  }
  return $object;
}

print_r($day);

输出:here

我明白为什么没有显示早餐,因为它当时不存在,所以我需要一种更好的迭代方式。

【问题讨论】:

  • 使用simpleXML!
  • 您的原始 xml 数据中也没有 fooddaytime。我唯一能看到的是,当元素类型匹配时,您使用名称为 &lt;complexType name="vegetable"&gt; 的 complexType 作为结果 json 中的子对象/数组。似乎这是一个 XSD 而不是 XML 文件。其余的还不清楚。
  • @JustOnUnderMillions 是的,我在 PHP 中定义了食物、日期和时间。是的,它是一个 XSD,但实际上只是想要在遍历子级之前循环遍历数组的第一级背后的逻辑。

标签: javascript php arrays iteration domdocument


【解决方案1】:

再添加一个替换所有已知类型的函数(我称之为replaceComplexTypes):

<?php

$data = '<xml>
<element name="breakfast" type="sandwich" />
<element name="lunch">
  <complexType>
    <element name="meat" type="string" />
    <element name="vegetables" type="vegetable" />
    <element name="chips" type="boolean" />
  </complexType>
</element>
<complexType name="sandwich">
  <element name="bread" type="string" />
  <element name="cheese" type="int" />
  <element name="butter" type="boolean" />
</complexType>
<complexType name="vegetable">
  <element name="tomato" type="int" />
  <element name="lettuce" type="boolean" />
  <element name="carrot" type="boolean" />
</complexType>
<element name="dinner" type="sandwich" />
</xml>';
$xml = new DOMDocument();
$xml->loadXML($data);

$day = getLevel1($xml->childNodes[0]);
$day2 = replaceComplexTypes($day['time'], $day['food']);
$day = array('time' => $day2, 'food' => $day['food']);

function getLevel1(DOMNode $domNode) {
  $day = array(
    "time" => array(),
    "food" => array()
  );
  foreach ($domNode->childNodes as $node) {
    if ($node->nodeName == "element") {
      if ($node->hasChildNodes()) {
        $day["time"][$node->getAttribute('name')] = getLevel2($node);
      } else {
          if (isset($day["food"][$node->getAttribute('type')])) {
            $day["time"][$node->getAttribute('name')] = $day["food"][$node->getAttribute('type')];
          } else {
            $day["time"][$node->getAttribute('name')] = $node->getAttribute('type');  
          }
      }
    };
    if ($node->nodeName == "complexType") {
      if ($node->hasChildNodes()) {
        $day["food"][$node->getAttribute('name')] = getLevel2($node);
      } else {
        $day["food"][$node->getAttribute('name')] = $node->getAttribute('type');
      }
    };
  }
  return $day;
}

function getLevel2(DOMNode $domNode) {
  $object = array();
  foreach ($domNode->childNodes as $node) {
    if ($node->nodeName == "element") {
      $object[$node->getAttribute('name')] = $node->getAttribute('type');
    };
    if ($node->hasChildNodes()) {
      if ($node->hasAttribute('name')) {
        $object[$node->getAttribute('name')] = getLevel2($node);
      } else {
        return getLevel2($node);
      }
    }
  }
  return $object;
}

function replaceComplexTypes(array $replaceIn, array $replaceWith) {
  $output = array();
  foreach ($replaceIn as $key => $value) {
    if (is_array($value)) {
      $output[$key] = replaceComplexTypes($value, $replaceWith);
    }
    else {
      if (array_key_exists($value, $replaceWith)) {
        $output[$key] = $replaceWith[$value];
      }
      else {
        $output[$key] = $value;
      }
    }
  }
  return $output;
}

print_r($day);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 2016-07-25
    • 2013-02-16
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 2011-08-15
    相关资源
    最近更新 更多