Andy
Andy

Reputation: 454

php loop not working as expected

I'm trying to swap all attribute id's at once from '$old' > '$new' then save the xml:

$reorder = array( 9=>"8", 8=>"5", 7=>"4", 6=>"3", 5=>"0", 4=>"1", 3=>"9", 2=>"7", 1=>"2", 0=>"6" );

    $objDOM = new SimpleXMLElement(some.xml, null, true);
    foreach ($reorder as $old => $new) {
       $picture = $objDOM->xpath('picture[@id="'.$old.'"]');
       $picture[0]["id"] = $new;
    }
    echo $objDOM->asXML();

The result below (doesn't match Array $reorder)

It seems to be switching the id's in sequence, so id's that have just been switched are then switched again if they come up later in the array.

What I'm doing wrong there? How can I get it to switch ALL the id's in one go?

Thanks... Andy

Upvotes: 0

Views: 171

Answers (2)

Josh Davis
Josh Davis

Reputation: 28730

Judging from the example contained in the question, I would simply iterate over all <picture/> elements and change @id accordingly. For instance:

foreach ($objDOM->picture as $picture)
{
    $id = (string) $picture['id'];
    $picture['id'] = $reorder[$id];
}

This assumes that $reorder has an entry for every @id used in the document. Otherwise, you'll need to use isset() to skip nodes that don't need to be changed.

Upvotes: 0

teemitzitrone
teemitzitrone

Reputation: 2260

The answer are two loops

fist you search the xpath for the old id, store it in an array and then loop again to replace the stored results with the new id

$reorder = array(9 => "8", 8 => "5", 7 => "4", 6 => "3", 5 => "0", 4 => "1", 3 => "9", 2 => "7", 1 => "2", 0 => "6");

$objDOM = new SimpleXMLElement(
      '<pictures>
    <picture id="9">id was 9, should be 8 now</picture>
    <picture id="8">id was 8, should be 5 now</picture>
    <picture id="7">id was 7, should be 4 now</picture>
    <picture id="6">id was 6, should be 3 now</picture>
    <picture id="5">id was 5, should be 0 now</picture>
    <picture id="4">id was 4, should be 1 now</picture>
    <picture id="3">id was 3, should be 9 now</picture>
    <picture id="2">id was 2, should be 7 now</picture>
    <picture id="1">id was 1, should be 2 now</picture>
    <picture id="0">id was 0, should be 6 now</picture>
</pictures>');
$oldPicIds = array();

foreach ($reorder as $old => $new) {
   $oldPicIds[$old] = $objDOM->xpath('picture[@id="' . $old . '"]');
}

foreach ($reorder as $old => $new) {
   $oldPicIds[$old][0]['id'] = $new;
}

echo $objDOM->asXML();

Output:

<?xml version="1.0"?>
<pictures>
    <picture id="8">id was 9, should be 8 now</picture>
    <picture id="5">id was 8, should be 5 now</picture>
    <picture id="4">id was 7, should be 4 now</picture>
    <picture id="3">id was 6, should be 3 now</picture>
    <picture id="0">id was 5, should be 0 now</picture>
    <picture id="1">id was 4, should be 1 now</picture>
    <picture id="9">id was 3, should be 9 now</picture>
    <picture id="7">id was 2, should be 7 now</picture>
    <picture id="2">id was 1, should be 2 now</picture>
    <picture id="6">id was 0, should be 6 now</picture>
</pictures>

to save an array you could use array_pop to get the last occurrence of picture@id=xy. which should be the wanted one (read comments for drawbacks)

$reorder = array(9 => "8", 8 => "5", 7 => "4", 6 => "3", 5 => "0", 4 => "1", 3 => "9", 2 => "7", 1 => "2", 0 => "6");

$objDOM = new SimpleXMLElement(
      '<pictures>...</pictures>');

foreach ($reorder as $old => $new) {
   $picture = $objDOM->xpath('picture[@id="' . $old . '"]');
   $picture = array_pop($picture);
   $picture['id'] = $new;
}

echo $objDOM->asXML();

Upvotes: 2

Related Questions