你如何一次迭代一个级别?

时间:2017-04-24 11:09:07

标签: javascript php arrays iteration domdocument

我们说我有类似的东西而且无法改变:

<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

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

1 个答案:

答案 0 :(得分:0)

再添加一个替换所有已知类型的函数(我称之为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);