Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PHP中使用XPath提取XML_Php_Xml_Xpath - Fatal编程技术网

在PHP中使用XPath提取XML

在PHP中使用XPath提取XML,php,xml,xpath,Php,Xml,Xpath,我有以下XML: <root> <level name="level1"> <!-- More children <level> --> </level> <level name="level2"> <!-- Some more children <level> --> </level> </root> 如何直

我有以下XML:

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

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

如何直接在
下提取
,以便相对于提取的
运行XPath查询,例如
$xml->XPath('//some query')

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

foreach ($levels as $level) {
   $levelname = $level->getAttribute('name');
      if ($levelname == 'level1') {
        //do stuff
      } 
}
我个人更喜欢解析XML的类。

的第二个参数是上下文节点。只需传递您以前“找到”的DOMNode实例,查询就会相对于该节点运行。例如

<?php
$doc = new DOMDocument;
$doc->loadxml( data() );

$xpath = new DOMXPath($doc);
$nset = $xpath->query('/root/level[@name="level1"]');
if ( $nset->length < 1 ) {
    die('....no such element');
}
else {
    $elLevel = $nset->item(0);

    foreach( $xpath->query('c', $elLevel) as $elC) {
        echo $elC->nodeValue, "\r\n";
    }
}


function data() {
    return <<< eox
<root>
    <level name="level1">
        <c>C1</c>
        <a>A</a>
        <c>C2</c>
        <b>B</b>
        <c>C3</c>
    </level>
    <level name="level2"> 
        <!-- Some more children <level> --> 
    </level> 
</root>
eox;
}
查询('/root/level[@name=“level1”]”); 如果($nset->长度<1){ 模具(“……无此类元件”); } 否则{ $elLevel=$nset->item(0); foreach($xpath->query($c',$elLevel)作为$elC){ echo$elC->nodeValue,“\r\n”; } } 函数数据(){ return用于解析XML/HTML使这一切变得非常简单

$qp = qp($xml) ;
$levels = $qp->find('root')->eq(0)->find('level') ;

foreach($levels as $level ){
    //do  whatever you want with it , get its xpath , html, attributes etc.
    $level->xpath() ; //
}

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表达式
根目录中的所有
级别
元素节点:
/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)
bool(true)
布尔结果 可以在Xpath中设置该条件并返回布尔值

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

float(1)
bool(true)

未理解。是否希望Xpath获取第一级节点?
/root/level[1]
是否有特殊原因需要将这些查询拆分为两部分?(可能有…)我设计的
XPath
仅在根目录中只有一个
时才起作用。您可以通过添加类似于
level[@name=“level2”]的谓词将其限制/固定到一个level元素
到您的查询。我唯一的问题是,我的
XPath
查询应该遵循此步骤,首先在xml中标识叶节点:元素的名称是
level
-而不是
level1
level1
是“only”属性
name
的一个值。据我所知,OP只需要第一个值。在这种情况下,他将在元素内使用
name
标记……但是getElementsByTagName不是这样做的。
name
是一个属性,
level1
是ex中属性
name
的值之一示例文档。getElementsByTagName不关心属性。示例文档中没有
元素->getElementsByTagName('level1')将返回空列表。@VolkerK您完全正确。我修改了我的答案。感谢您的观察。;-)现在是
,我可以在其上运行XPath查询,如$xml->Path('\\some query')
问题的一部分。我猜这才是真正的问题,而不是如何“查找/提取”一个特定的级别元素。但是的,这是推测。Querypath看起来非常有用。如何只
查找('level')
匹配某个属性,例如
level1l
?它是什么类型的许可证?我想应该是
->find('level[name=“level1”]”)
,即元素
level
的css3选择器,具有值为
level1
的属性
name
——除了在属性名称前没有@,它与本例中的xpath查询相同。在foreach循环中,获取级别usibg$level->attr('name')的属性名称然后将它与正则表达式进行比较。我不知道为什么我会被否决,但查询部分的功能非常广泛