简体   繁体   中英

Find if an element exists in XML using PHP DOM

I have a dom element of which i want to find if exists a specific sub-element.

My node is like this:

    <properties>
        <property name="a-random-neme" option="option2" >value1</property>
        <property name="another-random-name">V2</property>
        <property name="yet-another-random-name" option="option5" >K3</property>
    </properties>

in php it is referenced by a dom object

$properties_node;

In another part of php code I want to check if a datum I'm going to add already exists

    $datum = [ 'name'=>'yet-another-random-name', 'value'=>'K3'];
    //NOTE: If other attributes exists I want to keep them
    $prop=$dom->createElement('property',$datum['value']);
    $prop->setAttribute('name', $datum['name']);

    if(prop_list_contains($properties-node,$prop,['name']))
        $properties_node->appendChild($prop);
    else
        echo "not adding element, found\n";

now I want to make

    /**
     @param $properties_node reference to the existing dom object
     @param $prop the new element I want to add
     @param $required_matches an array containing the name of the attributes that must match

     @return matching element if match is found, false otherweise 
    */
    function prop_list_contains(&$properties_node,$prop,array $required_matches){
    // here I have no Idea how to parse the document I have

      return false
    }

Desiderata:

not adding element, found

The easiest way I can think if is to use XPath to check if the node already exists.

Assuming that you will only use 1 element to match on (more is possible, but much more complicated). This first extracts the value from the new node and then uses XPath to check if a matching value already exists in the current data.

The main thing about this process is to ensure you use the correct context for the search. This is effectively what to search in, first this uses the new element, then the current one to check it.

function prop_list_contains(DOMXPath $xp, $properties_node, $prop, 
        array $required_matches){
    // Extract value from new node
    $compare = $xp->evaluate('string(@'.$required_matches[0].')', $prop);
    // Check for the value in the existing data
    $xpath = 'boolean(./property[@'. $required_matches[0] . ' = "' . $compare . '"])';

    return ( $xp->evaluate($xpath, $properties_node) );
}

This will also mean you need to create the XPath object to pass in...

$xp = new DOMXPath($dom);

this saves creating it each time.

Also as this returns true if the node exists, you need to change your test to use ! ...

if( ! prop_list_contains($xp, $properties_node,$prop,['name'])) {
    $properties_node->appendChild($prop);
}
else    {
    echo "not adding element, found\n";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM