使用XPath在PHP中提取XML

时间:2015-09-09 17:23:23

标签: php xml xpath

我有一个XML:

<root>
   <level name="level1">
       <!-- More children <level> --> 
   </level>

   <level name="level2"> 
       <!-- Some more children <level> --> 
   </level> 
</root>

如何直接在<level>下提取<root>,以便相对于提取的$xml->xpath('\\some-query')运行<level>的XPath查询?

2 个答案:

答案 0 :(得分:4)

DOMXpath::evaluate()允许您从DOM中获取节点列表和标量值。

因此,您可以使用Xpath表达式直接获取值:

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

var_dump(
  $xpath->evaluate('string(/root/level[@name="level2"]/@name)')
);

输出:

string(6) "level2"

Xpath表达式

level中的所有root个元素节点:
/root/level

具有特定的名称属性:
/root/level[@name="level2"]

您要获取的值(name属性以进行验证):
/root/level[@name="level2"]/@name

投射到一个字符串中,如果找到了节点,结果将是一个空字符串:

string(/root/level[@name="level2"]/@name)

循环遍历节点,将它们用作上下文

如果您需要为节点执行多个表达式,最好单独获取它并使用foreach()DOMXpath::evaluate()的第二个参数是上下文节点。

foreach ($xpath->evaluate('/root/level[@name="level2"]') as $level) {
  var_dump(
    $xpath->evaluate('string(@name)', $level)
  );
}

节点列表长度

如果您需要处理,没有找到任何节点,您可以检查DOMNodeList::$length属性。

$levels = $xpath->evaluate('/root/level[@name="level2"]');
if ($levels->length > 0) {
  $level = $levels->item(0);
  var_dump(
    $xpath->evaluate('string(@name)', $level)
  );
} else {
  // no level found
}

count()表达式

您也可以使用count()表达式验证以前的元素。

var_dump(
  $xpath->evaluate('count(/root/level[@name="level2"])')
);

输出:

float(1)

布尔结果

可以在Xpath中创建一个条件并返回布尔值。

var_dump(
  $xpath->evaluate('count(/root/level[@name="level2"]) > 0')
);

输出:

bool(true)

答案 1 :(得分:1)

这应该有效:

$dom = new DOMDocument;
$dom->loadXML($xml);
$levels = $dom->getElementsByTagName('level');

foreach ($levels as $level) {
   $levelname = $level->getAttribute('name');
      if ($levelname == 'level1') {
        //do stuff
      } 
}

我个人更喜欢DOMNodeList类来解析XML。