根据属性选择节点并更改子节点

I have following XML file:

<?xml version="1.0" encoding="UTF-8"?>
<programmedata>
<programme id="1">
<name>Left</name>
<image_path></image_path>
<rating_point>0</rating_point>
<five_star>0</five_star>

With following code I am trying to edit value of rating_point:

$xml=simplexml_load_file("content.xml");
if(!empty($_POST["rating"]) && !empty($_POST["voted_programme"])){
    try{
     $rating = $_POST["rating"];
        $i = $_POST['voted_programme'];
        $xml->programme[$i]->rating_point = $rating;
        if($rating == '5')
        {
            $xml->programme[$i]->five_star = $rating;
        }

but getting error:
Notice: Indirect modification of overloaded element of SimpleXMLElement has no effect in ...

tried different solution but seems not working.

Your statement $xml->programme[1]->rating_point does not select the <programme> node with the attribute id="1".
It refers to the 2nd <programme> node in your XML, regardless of its id attribute.

There are basically 2 ways to get to <programme id="1">:

$xml = simplexml_load_string($x); // assume XML in $x
$rating = 5;
$id = 1;

#1 looping the entire XML

foreach ($xml->programme as $item) {

    if ($item[`id`] == $id) { 

        $item->rating_point = $rating;
        if ($rating == 5) $item->five_star = $rating;
    }
}

Comment: see line 2 (if...) on how to access attributes.
see it working: https://eval.in/458300

#2 select with xpath:

$item = $xml->xpath("//programme[@id='$id']")[0];

if (!is_null($item)) {
    $item->rating_point = $rating;
    if ($rating == 5) $item->five_star = $rating;
} 

Comments:

  • //programme: select every <programme> node, wherever in the XML tree
  • [@id='1']: a condition, @ is for attribute
  • the xpath function returns an array of SimpleXML elements, with the [0] we grab the first element in that array and put it into $item.

see it working: https://eval.in/458310

As you can see, solution #2 is faster, even more so if your XML contains several <programme> nodes.