2017-04-24 37 views
0

比方说,我有这样的事情,它不能被改变:你如何一次迭代一个级别?

<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

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

+0

使用'simpleXML'! – JustOnUnderMillions

+0

你的原始xml数据中也没有“食物”或“天”或“时间”。我能看到的唯一情况是,当元素类型匹配时,在结果json中使用复杂类型名称为“作为子对象/数组。看起来这是一个XSD而不是一个XML文件。其余的很不清楚。 – JustOnUnderMillions

+0

@JustOnUnderMillions是的我在PHP中定义食物,日期和时间。是的,它是一个XSD,但实际上只是希望在通过子节点之前循环遍历数组的第一级。 – Craig

回答

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);