Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't changing an xml value with PHP

Tags:

dom

php

xml

This is my XML-file:

<todos>
  <todo>
    <titel>sasd</titel>
    <erstellt>2012-04-30 17:19:21</erstellt>
    <erledigen_bis>2012-05-03</erledigen_bis>
    <erledigt>Nein</erledigt>
    <thingstodo>sffsdfdf</thingstodo>
  </todo>
</todos>

Now I want to change the value inside of the <erledigt> tag to 'Ja'.

I tried this with the following code:

<?php
$filename = 'xml/todos.xml';

$xmlDoc = new DOMDocument();
$xmlDoc->load('xml/todos.xml');

$todos = $xmlDoc->getElementsByTagName('todo');         

foreach ($todos as $todo) {

    $titel = $todo->getElementsByTagName('titel');
    $actualTitel = $titel->item(0)->nodeValue;
    $paramTitel = $_GET["titel"];

    $erstellt = $todo->getElementsByTagName('erstellt');    
    $actualTimestamp = $erstellt->item(0)->nodeValue;
    $paramTimestamp = $_GET["timestamp"];

    if ($paramTitel == $actualTitel && $paramTimestamp == $actualTimestamp) {

        $todo->erledigt= 'Ja';

    }
}

$xmlDoc->save($filename);

header('Location: todo.php');
?>

Please help me, I searched for about 5 hours on the web and couldn't find any solution for my problem.

like image 432
alderos Avatar asked Jan 17 '23 19:01

alderos


2 Answers

$todo->erledigt doesn't work in DOMDocument, only SimpleXML can do that. You need to use getElementsByTagName again.

You also need to use nodeValue to get/set the value of the element.

if ($paramTitel == $actualTitel && $paramTimestamp == $actualTimestamp) {
    $todo->getElementsByTagName('erledigt')->item(0)->nodeValue = 'Ja';
}

DEMO: http://codepad.org/xJbQmO2u

like image 148
Rocket Hazmat Avatar answered Jan 24 '23 20:01

Rocket Hazmat


As you are looking for specific elements inside the document, I suggest highly you locate them by using xpath:

$xp = new DOMXPath($doc);
$expression = sprintf('//todo[titel = "%s" and erstellt = "%s"]/erledigt', $_GET["titel"], $_GET["timestamp"]);
$result = $xp->query($expression);
foreach ($result as $node) {
    $node->nodeValue = 'Ja';
}

This results into the following (exemplary) xpath expression:

//todo[titel = "sasd" and erstellt = "2012-04-30 17:19:21"]/erledigt

Which will select all erledigt nodes that are part of a todo node that have the titel and erstellt node values as specified.

You can then easily change it. Additionally you're looking for erledigt nodes that aren't "erledigt" yet, but the current variant already doesn't hurt.

Demo/Full Code Example:

<?php
/**
 * @link http://stackoverflow.com/q/10388661/367456
 */

$_GET["titel"] = 'sasd';
$_GET["timestamp"] = '2012-04-30 17:19:21';

$xml = '<todos>
  <todo>
    <titel>sasd</titel>
    <erstellt>2012-04-30 17:19:21</erstellt>
    <erledigen_bis>2012-05-03</erledigen_bis>
    <erledigt>Nein</erledigt>
    <thingstodo>sffsdfdf</thingstodo>
  </todo>
</todos>';

$doc = new DOMDocument();
$doc->loadXML($xml);
$xp = new DOMXPath($doc);
$expression = sprintf('//todo[titel = "%s" and erstellt = "%s"]/erledigt', $_GET["titel"], $_GET["timestamp"]);
$result = $xp->query($expression);
foreach ($result as $node) {
    $node->nodeValue = 'Ja';
}

echo $doc->saveXML();
like image 26
hakre Avatar answered Jan 24 '23 20:01

hakre