Search code examples
phpxmlxpathxpathquery

PHP + XPath Query get Child Nodes and their values


I have a XML file record.xml which looks like:

<record>
    <name>john</name>
    <gender>male</gender>
    <subject>mathematics, english, science</subject>
</record>
<record>
    <name>jamie</name>
    <gender>female</gender>
    <subject>mathematics, science</subject>
</record>
<record>
    <name>jack</name>
    <gender>male</gender>
    <subject>social-science, english</subject>
</record>

I want to write a xpath query which will return all the child nodeName of <record> and value of all these child nodes in an associative array.

For Ex.:

For above XML file Output array should be-

array{
     [0] => array{
                 [name] = 'john',
                 [gender] = 'male',
                 [subject] = 'mathematics, english, science' 
            }
     [1] => array{
                 [name] = 'jamie',
                 [gender] = 'female',
                 [subject] = 'mathematics, science' 
            }
     [2] => array{
                 [name] = 'jack',
                 [gender] = 'male',
                 [subject] = 'social-science, english' 
            }
}

Below is part of Code I written this return all the <record> child nodes values but not their node name.

    .......
    .......
    $xmldoc = new DOMDocument();
    $xmldoc->load('record.xml');
    $xpathvar = new Domxpath($xmldoc);
    $res = $xpathvar->query('//record');
    foreach($res as $data){
            //$data do not contain node values
           $arr[] = $data->textContent;
    }
    //process $arr to get required format
     .....
     .....

I just want a Xpath query which will return child node names along with their values.


Solution

  • Problem is a record as a node is just part of the node hierarchy. What you're getting is all records, however you also want to descend and get the data from the record's child nodes. A very case specific example is :

    <?php     
    $xmldoc = new DOMDocument();
    $xmldoc->load('record.xml');
    $xpathvar = new Domxpath($xmldoc);
    $res = $xpathvar->query('//record');
    foreach($res as $data){
        $narr = [];
        foreach ($data->childNodes as $cnode) {
            $narr[$cnode->nodeName] = $cnode->nodeValue;
        }
        $arr[] = $narr;
    
    }    
    print_r($arr);
    

    Should output something like:

    Array
    (
        [0] => Array
            (
                [name] => john
                [gender] => male
                [subject] => mathematics, english, science
            )
    
        [1] => Array
            (
                [name] => jamie
                [gender] => female
                [subject] => mathematics, science
            )
    
        [2] => Array
            (
                [name] => jack
                [gender] => male
                [subject] => social-science, english
            )
    
    )
    

    NOTE: This solution is very case specific and would probably break if you have additional nested hierarchies (which I recommend you do in order to store the multiple subjects).