使用php从xml文件中获取嵌套标记值

时间:2014-03-29 19:33:12

标签: php xml dom xml-parsing

我有一个特殊格式的xml文件如何从中获取嵌套标签值,例如,如果我想要不透明度,厚度,重复,旋转标签分别为第一个dict标签的值为1,0,false,90其他人一样。请指出我正确的方向

<?xml version="1.0" encoding="UTF-8"?>
<pu version="1.0">
  <dict>
    <key>ID</key>
    <string>C0AC8773-CEE6-4A12-9C69-320A1BDB7255</string>
    <key>Items</key>
    <array>
      <dict>
        <key>opacity</key>
        <real>1</real>
        <key>Thickness</key>
        <real>0</real>
        <key>repeat</key>
        <false/>
        <key>rotation</key>
        <real>90</real>
      </dict>
      <dict>
        <key>opacity</key>
        <real>1</real>
        <key>Thickness</key>
        <real>0</real>
        <key>repeat</key>
        <false/>
        <key>rotation</key>
        <real>180</real>
      </dict>
      <dict>
        <key>opacity</key>
        <real>1</real>
        <key>Thickness</key>
        <real>0</real>
        <key>repeat</key>
        <false/>
        <key>rotation</key>
        <real>270</real>
      </dict>
    </array>
  </dict>
</pu>

这就是我想要的

$dom = new DOMDocument;
$dom->load($path);
$array = $dom->getElementsByTagName('array');
foreach($array as $dict)
{
   foreach($dict as $key->$value)
    {
      print_r("key = ".$key." value = ".$value);//i.e. key = opacity value = 1
    }
}

我做错了什么,并提前感谢

2 个答案:

答案 0 :(得分:2)

$dom = new DOMDocument;
$dom->loadXML($xml);
$xpath = new DOMXpath($dom);
$dicts = $xpath->query("/pu/dict/array/dict");

foreach($dicts as $dict) { 
    $childNodes = $dict->childNodes;
    foreach ($childNodes as $child) {
        if ($child->nodeName !== 'key') {
            continue;
        }
        echo $child->nodeValue . " " . getNextSibling($child) . "<br>";
    }
}

function getNextSibling($node) {
    return ($node->nodeType === 3) ? $node->nextSibling->nodeValue : $node->nextSibling->nextSibling->nodeValue;
}

See it in action

答案 1 :(得分:-1)

这是两份工作。您必须迭代dict元素并获取所有key元素。第二个获取每个key元素的值节点,并根据其名称对其进行解析。

DOMXpath :: evaluate()或query()可以使用上下文节点获取第二个参数。 Xpath表达式将相对于它。

在根级/pu/dict获取文档元素的所有dict个子级。

$result = [];
$dicts = $xpath->evaluate('/pu/dict');
foreach ($dicts as $dict) {
  $result[] = getList($xpath, $dict);
}

getList()函数key内部用于获取key节点的dict子元素。

function getList($xpath, $node) {
  $items = $xpath->evaluate('key', $node);
  $result = [];
  foreach ($items as $item) {
    $result[$item->nodeValue] = getValue($xpath, $item);
  }
  return $result;
}

值节点是每个key元素后面的元素。在Xpath中following-sibling::*[1]。值类型取决于节点名称。大多数只是标量值。如果是array,请抓取dict元素子元素并为每个元素调用getList()

function getValue($xpath, $node) {
  $valueNode = $xpath->evaluate('following-sibling::*[1]', $node)->item(0);
  switch ($valueNode->nodeName) {
  case 'array' : 
    $dicts = $xpath->evaluate('dict', $valueNode);
    foreach ($dicts as $dict) {
      $result[] = getList($xpath, $dict);
    }
    return $result;
  case 'true' :
    return TRUE;
  case 'false' :
    return FALSE;
  case 'real' :
    return (float)$valueNode->nodeValue;
  case 'string' :
    return $valueNode->nodeValue;
  }
}

放在一起:https://eval.in/private/b88a430a237494

$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<pu version="1.0">
  <dict>
    <key>ID</key>
    <string>C0AC8773-CEE6-4A12-9C69-320A1BDB7255</string>
    <key>Items</key>
    <array>
      <dict>
        <key>opacity</key>
        <real>1</real>
        <key>Thickness</key>
        <real>0</real>
        <key>repeat</key>
        <false/>
        <key>rotation</key>
        <real>90</real>
      </dict>
      <dict>
        <key>opacity</key>
        <real>1</real>
        <key>Thickness</key>
        <real>0</real>
        <key>repeat</key>
        <false/>
        <key>rotation</key>
        <real>180</real>
      </dict>
      <dict>
        <key>opacity</key>
        <real>1</real>
        <key>Thickness</key>
        <real>0</real>
        <key>repeat</key>
        <false/>
        <key>rotation</key>
        <real>270</real>
      </dict>
    </array>
  </dict>
</pu>
XML;

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);

function getValue($xpath, $node) {
  $valueNode = $xpath->evaluate('following-sibling::*', $node)->item(0);
  switch ($valueNode->nodeName) {
  case 'array' : 
    $dicts = $xpath->evaluate('dict', $valueNode);
    foreach ($dicts as $dict) {
      $result[] = getList($xpath, $dict);
    }
    return $result;
  case 'true' :
    return TRUE;
  case 'false' :
    return FALSE;
  case 'real' :
    return (float)$valueNode->nodeValue;
  case 'string' :
    return $valueNode->nodeValue;
  }
}

function getList($xpath, $node) {
  $items = $xpath->evaluate('key', $node);
  $result = [];
  foreach ($items as $item) {
    $result[$item->nodeValue] = getValue($xpath, $item);
  }
  return $result;
}

$result = [];
$dicts = $xpath->evaluate('/pu/dict');
foreach ($dicts as $dict) {
  $result[] = getList($xpath, $dict);
}

var_dump($result);