在PHP中使用XPath提取XML
我有以下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> 如何直
<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')的属性名称然后将它与正则表达式进行比较。我不知道为什么我会被否决,但查询部分的功能非常广泛