使用Simplexml的XPath根据PHP中的值过滤节点

2022-04-13 00:00:00 xml xpath php simplexml

我正在研究一种根据PHP中的值过滤某些节点的方法。我正在尝试返回等于‘Funded’的状态节点的计数。 我不确定的部分是使用数组(新过滤器($XML_BIO_CHILDS)中前一个过滤器($XML_BIO_RECORD[0])的结果)。
此代码不返回$count_c的计数。我如何根据Status="Funded"进行筛选?感谢您的任何线索。

以下是XML:

<?xml version="1.0" encoding="utf-8"?>
<data>
<record id="1A">
    <congrant>
        <ident>a</ident>
        <status>Not Funded</status>
    </congrant>
    <congrant>
        <ident>b</ident>
        <status>Funded</status>
    </congrant>
    <congrant>
        <ident>c</ident>
        <status/>
    </congrant>
</record>
<record id="1B">
    <congrant>
        <ident>a</ident>
        <status>Not Funded</status>
    </congrant>
    <congrant>
        <ident>b</ident>
        <status>Funded</status>
    </congrant>
    <congrant>
        <ident>c</ident>
        <status/>
    </congrant>
</record>
<record id="1C">
    <congrant>
        <ident>aaa</ident>
        <status>Funded</status>
    </congrant>
    <congrant>
        <ident>bbb</ident>
        <status>Funded</status>
    </congrant>
    <congrant>
        <ident>c</ident>
        <status>Funded</status>
    </congrant>
</record>
</data>

以下是PHP:

$url_bio = "test.xml";


$xml_bio = simplexml_load_file($url_bio);

$xml_bio_record=$xml_bio->xpath('/data/record');
$count_a = count($xml_bio_record);
echo '<br>$count_a is...'.$count_a.'<br>';//
foreach($xml_bio_record as $xa){
    echo "Found {$xa->status} <br>";
}

$xml_bio_record=$xml_bio->xpath('//record[@id="1A"]');
$count_b = count($xml_bio_record);
echo '<br>$count_b is...'.$count_b.'<br>';//
foreach($xml_bio_record as $xb){
    echo "Found {$xb->status} <br>";
}



$xml_bio_children=$xml_bio_record[0]->xpath('/congrant[status="Funded"]');

$count_c = count($xml_bio_children);
echo '<br>$count_c is...'.$count_c.'<br>';//
foreach($xml_bio_children as $xc){
    echo "Found {$xc->status} <br>";
}
= 作为补充,如果我希望将变量设置为等于$xb->xpath('./congrant[status="Funded"]'),例如:$xml_congrant_congrant_children=$xb->xpath('./congrant[status="Funded"]'),然后在分页场景中使用索引循环访问基金结果,那么如何实现呢? 例如

for ($i = $offset; $i < ($offset + $per_page); $i++)
 { 
$strCongrant_ident = $xml_congrant_congrant_children[$i]['ident'];
} 

我以前在分页设置中使用过这种循环思想,但让筛选器应用到这里的变量并不起作用。感谢您的任何线索。


解决方案

如supputuri's answer所示,您可以将两个XPath表达式合并为一个搜索:

//record[@id="1A"]/congrant[status="Funded"]

如果您想要第一个列表用于其他目的,您可以循环遍历它并在PHP中执行状态检查:

$xml_bio_record=$xml_bio->xpath('//record[@id="1A"]');
$funded_count = 0;
foreach($xml_bio_record as $xb){
    foreach ($xb->congrant as $congrant) {
        if ( (string)$congrant->status == 'Funded' ) {
            $funded_count++;
        }
    }
}

或者您可以混合使用循环和XPath,使用.相对于特定元素进行XPath搜索:

$xml_bio_record=$xml_bio->xpath('//record[@id="1A"]');
$total_funded_count = 0;
foreach($xml_bio_record as $xb){
    $xb_funded_count = count($xb->xpath('./congrant[status="Funded"]'));
    $total_funded_count += $xb_funded_count;
}

相关文章