I'm pulling data from and XML page and trying to write back to it with some PHP code. I have successfully done this by pulling the individual nodes with item(0) and getAttributeNode
, then saving back to nodeValue
instead of with setAttribute
. My goal, however, is to make the code work with a foreach
statement so that I don't have to go back in and edit it if trails are added and removed.
If I try to change it with setAttribute
it doesn't work in either scenario (pulling them individually or with the foreach
statement), and I can't figure out how to make the getAttributeNode
and nodeValue
work with a foreach
statement. I think I may need an array but nothing I've tried has worked so far. I can get the page to load without an error but nothing happens when I click the submit button.
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<?php
$xml = new DOMDocument('1.0', 'utf-8');
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xml->load('example.xml');
$xpath = new DOMXpath($xml);
$childForm = '';
foreach ( $xpath->query("//trails/trail") as $trail ) {
$childForm .= "<form action=''>
<span class=\"title\">".$trail->getAttribute("name")."</span> <span class=\"title\">Status</span>
<select name=\"asstatusform\" >
<option selected value=".$trail->getAttribute("status").">".$trail->getAttribute("status")."</option>
<option value=\"OPEN\">OPEN</option>
<option value=\"CLOSED\">CLOSED</option>
<option value=\"RACING CLOSURE\">RACING CLOSURE</option>
</select></span>
<br>
</form>";
}
?>
<form action="" method="POST">
<?php echo $childForm; ?>
<input name="submit" type="submit" value="Save" />
</form>
<?php
if (isset($_POST['submit']))
{
$trail->setAttribute('status', $_POST['asstatusform']);
htmlentities($xml->save('example.xml'));
}
?>
You say you want to edit this attribute "with a foreach statement" but you've got your setAttribute
call outside the loop so you're only changing the last item. You're also nesting forms inside each other, which does not work.
If I'm understanding correctly, you want to individually update each of the trails' states, based on the form submission. To do that you'll need to submit an array back to the form and then loop through it. The potentially tricky part is matching the array with the the contents of the XML. Ideally you have some kind of unique identifier, but in this code I'm just assuming the order of the XML elements won't change between display and processing. So first POST entry is the first XML element, etc.
<?php
$xml = new DOMDocument;
$xml ->load('example.xml');
$xpath = new DOMXpath($xml);
$trails = $xpath->query("//trails/trail");
if (isset($_POST["submit"])) {
foreach ($_POST["asstatusform"] as $k=>$state) {
$trails->item($k)->setAttribute("status", $state);
}
$xml->save('example.xml');
}
?>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<form action="" method="POST">
<?php foreach ($trails as $trail): ?>
<span class="title"><?= htmlspecialchars($trail->getAttribute("name")) ?></span>
<span class="title">Status</span>
<select name="asstatusform[]">
<option selected value="<?= htmlspecialchars($trail->getAttribute("status")) ?>">
<?= htmlspecialchars($trail->getAttribute("status")) ?>
</option>
<option value="OPEN">OPEN</option>
<option value="CLOSED">CLOSED</option>
<option value="RACING CLOSURE">RACING CLOSURE</option>
</select>
</span>
<br/>
<?php endforeach; ?>
<input name="submit" type="submit" value="Save" />
</form>
Your inline HTML was giving me a headache, I can imagine you felt the same typing it out. Just break out of PHP for long blocks of HTML. I've used the alternative syntax for the foreach
loop, and short echo tags for output. Don't forget to always use htmlspecialchars()
to escape output to HTML pages.