区分 PHP XPath 中的相同节点名称

Differentiate between same node names in PHP XPath

我正在使用 PHP DOM XPath 读取 XML。 XML 在我卡住的地方有以下结构

<details>
    <name>name1</name>
    <address>address1</address>
</details>
<details>
    <name>name2</name>
    <mobile>mobileNum</mobile>
    <address>address2</address>
</details>

我有这样的数组

  array(
        'name',
        'mobile',
        'address'
    ); 

我使用此数组并从 XML 读取值并将该值存储在其他数组中,但在第一条记录中 手机号码 不存在,因此它读取手机号从第二条记录并将其插入第一条记录。

预期输出为

array
(

    [0] => array(

                'person_name' = name1,
                'address' = address1
                )
    [1] => array(

                'person_name' = name1,
                'mobile_no' = mobileNum
                'address' = address1
                )
)

但是我得到的输出是

array
(

    [0] => array(

                'person_name' = name1,
                'mobile_no' = mobileNum
                'address' = address1
                )
    [1] => array(

                'person_name' = name1,
                'address' = address1
                )
)

如何区分两个同名节点的值。

读取 XML 的代码是

$nodes = array
(
    'person_name' => 'name',
    'mobile_no'   => 'mobile',
    'address'     => 'address'
)

$final_data = array();

$node_values = '';

foreach($nodes as $key => $data)
{   
    $node_values = $xml->xpath('//details'.$data); 

    $node_values = json_decode(json_encode((array)$node_values), TRUE);

    if(!empty($node_values))    
    {   
        $i = 0;

        foreach($node_values as $d)
        {
            $final_data[$i][$key] = trim($d[0]);

            $i++;
        }
    }
}

这是一个工作示例,其中包含解释其工作原理的注释:

https://3v4l.org/ICO5i

<?php

// First of all, I've added <root> element to your XML document,
// because otherwise it's invalid. 
// But it's not important for the rest of the code.
//
// Also I've added additional <somethingelse> tag to show that filtering is working
$xmlString = '<root><details>
    <name>name1</name>
    <address>address1</address>
</details>
<details>
    <name>name2</name>
    <mobile>mobileNum</mobile>
    <address>address2</address>
    <somethingelse>This will be filtered</somethingelse>
</details></root>';


$xml = new SimpleXMLElement($xmlString);
//array_flip to get node names as keys for later foreach loop
$nodes = array_flip(array
(
    'person_name' => 'name',
    'mobile_no'   => 'mobile',
    'address'     => 'address',
));

$final_data = array();

//Here are all <details> sections' data in array.
$node_values = $xml->xpath('//details'); 
$node_values = json_decode(json_encode((array)$node_values), TRUE);

//this loop filters XML data from keys not existing in $nodes,
// which are the only that you want to keep
foreach($node_values as $node) {
    $final_data[] = array_intersect_key($node, $nodes);
}

var_dump($final_data);

我假设您要过滤 XML 未列在 $nodes 数组中的数据。否则,如果您不介意拥有比您需要的更多的数据,您可以跳过 foreach 循环并使用 $node_values 作为您的最终数据。