0

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
0

1 Answer 1

2

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";
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.