Page 1 of 1

Switching the order of XML children

Posted: Sat Feb 14, 2009 4:17 pm
by Still Learning
Hi. I'm trying to write a code to move a song up the playlist (which is an XML sharable playlist file[xspf]). Basically I want to take all the attributes of one child and switch them with the child below.

My code is successfully moving the second song to the first, but I can't seem to get the first song back down. (The output is the song that's moved up just prints twice.) :banghead:

Anyone see anything wrong with the code?

Code: Select all

 
<?php
$artist= $_POST["artist"];
$songnumber= $_POST["song_number"];
$root = $_SERVER['DOCUMENT_ROOT'];
$file = $root . "/wherefilesarestored/" . $artist . ".xspf";
$xml = simplexml_load_file($file) or die ("Unable to load XML file!");
$i= 0;
while ($i <= $songnumber)
{
if ($i == $songnumber)
 {
 $tempxml= $xml;
 foreach ($tempxml->trackList->track[$i-1]->children() as $child)
 //save info from top track
 {
 $chilname= $child->getName();
  switch ($chilname)
  {
  case "annotation" :
     $tempxml->trackList->track[$i-1]->annotation= $child;
  break;
  case "image" : $tempxml->trackList->track[$i-1]->image= $child;
  break;
  case "location" : $tempxml->trackList->track[$i-1]->location= $child;
  break;
  case "info" : $tempxml->trackList->track[$i-1]->info= $child;
  break;
  case "purchase" : $tempxml->trackList->track[$i-1]->purchase= $child;
  break;
  default: echo "There was an error.  <BR><BR>";
  break;
  } // end of switch
  } //end of for each
 
 foreach ($xml->trackList->track[$i]->children() as $child)
 //write all the info from bottom track to top track and vice versa
 {
 $chilname= $child->getName();
  switch ($chilname)
  {
  case "annotation" :
  $xml->trackList->track[$i-1]->annotation= $child;
  $xml->trackList->track[$i]->annotation= $tempxml->trackList->track[$i-1]->annotation;
  break;
  case "image" :
  $xml->trackList->track[$i-1]->image= $child;
  $xml->trackList->track[$i]->image = $tempxml->trackList->track[$i-1]->image;
  break;
  case "location" :
  $xml->trackList->track[$i-1]->location= $child;
  $xml->trackList->track[$i]->location= $tempxml->trackList->track[$i-1]->location;
  break;
  case "info" :
  $xml->trackList->track[$i-1]->info= $child;
  $xml->trackList->track[$i]->info= $tempxml->trackList->track[$i-1]->info;
  break;
  case "purchase" :
  $xml->trackList->track[$i-1]->purchase= $child;
  $xml->trackList->track[$i]->purchase= $tempxml->trackList->track[$i-1]->purchase;
  break;
  default: echo "There was an error.  <BR><BR>";
  break;
  } // end of switch
  } //end of for each
  
 
 
 } //end of if
 
 $i++;
} //end of while
$songnumber++;
 
$xml->asXML($file);
echo "Song number " . $songnumber . " has been successfully moved up 1 position on your playlist. <br />";
?>
 

Re: Switching the order of XML children

Posted: Mon Feb 16, 2009 9:53 pm
by Still Learning
Anyone have any ideas? I tried changing a bunch of stuff yesterday and just wound up banging my head for hours.

I know with any programming language to swap values of 2 variables, say $a and $b, all you'd need is a third $temp variable to assign the value of the first to, then say $a=$b; and then $b=$temp;

That's the basic logic I used for the code, but I can't figure out why it's not working.

Re: Switching the order of XML children

Posted: Tue Feb 17, 2009 4:08 am
by mintedjo
Can you not just do it exactly like you a,b, temp example?

Code: Select all

$temp = $xml->trackList->track[$i-1];
$xml->trackList->track[$i-1] = $xml->trackList->track[$i];
$xml->trackList->track[$i] = $temp;

Re: Switching the order of XML children

Posted: Tue Feb 17, 2009 12:45 pm
by Still Learning
mintedjo wrote:Can you not just do it exactly like you a,b, temp example?

Code: Select all

$temp = $xml->trackList->track[$i-1];
$xml->trackList->track[$i-1] = $xml->trackList->track[$i];
$xml->trackList->track[$i] = $temp;

Nope. That was exactly the first thing I tried. All that does is delete all the children of "track". So basically it makes 2 empty spots instead of swapping the order. The code I posted in the OP is on the right track, I just can't figure out what's wrong with the logic.

:banghead:

Re: Switching the order of XML children

Posted: Tue Feb 17, 2009 4:29 pm
by Still Learning
Now I'm really confused. For some reason the 2nd for each loop is changing the value of a variable that isn't even in it. This is the code I've gotten up to now still troublshooting, exporting values of vars at different times.

Code: Select all

<?php
$artist= $_POST["artist"];
$songnumber= $_REQUEST["song_number"]+1;
$root = $_SERVER['DOCUMENT_ROOT'];
$file = $root . "/wherefileisstored/" . $artist . ".xspf";
$xml = simplexml_load_file($file) or die ("Unable to load XML file!");
 
echo "song number sent= " . $songnumber . "<BR>";
 
foreach ($xml->trackList[0]->track[$songnumber-2]->children() as $child)
 //save info from top track into separate variables
 {
 $chilname= $child->getName();
  switch ($chilname)
  {
  case "annotation" :
     $anno1 = $child;
     echo "anno1 = " . $anno1 . "<BR>";
  break;
  case "image" : $image1 = $child;
  break;
  case "location" : $loc1 = $child;
  break;
  default: echo "There was an error.  <BR><BR>";
  break;
  } // end of switch
  } //end of for each
 
echo "Anno1 before 2nd for each = " . $anno1 . "<BR>";
 foreach ($xml->trackList[0]->track[$songnumber-1]->children() as $sec)
 //write all the info from bottom track to top track
 {
 $chilname= $sec->getName();
  switch ($chilname)
  {
  case "annotation" :
  $xml->trackList[0]->track[$songnumber-2]->annotation= $sec;
 
  break;
  case "image" :
  $xml->trackList[0]->track[$songnumber-2]->image= $sec;
 
  break;
  case "location" :
  $xml->trackList[0]->track[$songnumber-2]->location= $sec;
 
  break;
   default: echo "There was an error.  <BR><BR>";
  break;
  } // end of switch
  } //end of for each
 echo "Anno1 after 2nd for each = " . $anno1 . "<BR>";
 
 $xml->trackList[0]->track[$songnumber-1]->annotation= $anno1;
echo "<BR>";
$xml->trackList[0]->track[$songnumber-1]->image = $image1;
$xml->trackList[0]->track[$songnumber-1]->location= $loc1;
 
 
echo "<br>Song num - 2 = " . $xml->trackList->track[$songnumber-2]->annotation . "<BR>";
echo "<br>Song num - 1 = " . $xml->trackList->track[$songnumber-1]->annotation . "<BR>";
$xml->asXML($file);
 
echo "Song number " . $songnumber . " has been successfully moved up 1 position on your playlist. <br />";
?>
OUTPUT:
song number sent= 2
anno1 = Drown You
Anno1 before 2nd for each = Drown You
Anno1 after 2nd for each = Rebate


Song num - 2 = Rebate

Song num - 1 = Rebate
Song number 2 has been successfully moved up 1 position on your playlist.

Re: Switching the order of XML children

Posted: Tue Feb 17, 2009 4:58 pm
by Still Learning
I took out the 2nd for each loop and changed the values directly, and I'm still getting the same problem. How the heck is the value for $anno1 getting changed when it's not even referenced again?????

Code: Select all

<?php
$artist= $_POST["artist"];
$songnumber= $_REQUEST["song_number"]+1;
$root = $_SERVER['DOCUMENT_ROOT'];
$file = $root . "/xspf/" . $artist . ".xspf";
$xml = simplexml_load_file($file) or die ("Unable to load XML file!");
 
echo "song number sent= " . $songnumber . "<BR>";
 
foreach ($xml->trackList[0]->track[$songnumber-2]->children() as $child)
 //save info from top track into separate variables
 {
 $chilname= $child->getName();
  switch ($chilname)
  {
  case "annotation" :
     $anno1 = $child;
     echo "anno1 = " . $anno1 . "<BR>";
  break;
  case "image" : $image1 = $child;
  break;
  case "location" : $loc1 = $child;
  break;
  default: echo "There was an error.  <BR><BR>";
  break;
  } // end of switch
  } //end of for each
 
echo "Anno1 before swapping track children = " . $anno1 . "<BR>";
 
$xml->trackList[0]->track[$songnumber-2]->annotation= $xml->trackList[0]->track[$songnumber-1]->annotation;
$xml->trackList[0]->track[$songnumber-2]->image= $xml->trackList[0]->track[$songnumber-1]->image;
 
$xml->trackList[0]->track[$songnumber-2]->location= $xml->trackList[0]->track[$songnumber-1]->location;
 
echo "Anno1 after changing values of tracks = " . $anno1 . "<BR>";
 
 
 $xml->trackList[0]->track[$songnumber-1]->annotation= $anno1;
echo "<BR>";
$xml->trackList[0]->track[$songnumber-1]->image = $image1;
$xml->trackList[0]->track[$songnumber-1]->location= $loc1;
 
 
echo "<br>Song num - 2 = " . $xml->trackList->track[$songnumber-2]->annotation . "<BR>";
echo "<br>Song num - 1 = " . $xml->trackList->track[$songnumber-1]->annotation . "<BR>";
$xml->asXML($file);
 
echo "Song number " . $songnumber . " has been successfully moved up 1 position on your playlist. <br />";
?>
OUTPUT:
song number sent= 2
anno1 = Drown You
Anno1 before swapping track children = Drown You
Anno1 after changing values of tracks = Rebate


Song num - 2 = Rebate

Song num - 1 = Rebate (If Anno1 didn't change values it should say "Drown You")
Song number 2 has been successfully moved up 1 position on your playlist.

Re: Switching the order of XML children

Posted: Wed Feb 18, 2009 8:47 am
by mintedjo
I'm guessing now... I dont know anything about simplexml (and little about php for that matter :-P)

When you have two objects; A and B, the variables A and B hold references or memory locations, not the actual object.
If you do something like:
A = B;
What actually happens is the reference to object B is copied into variable A.
That means that even if you had 2 variables pointing to different objects in memory you now have 2 variables pointing to the same object. If you aren't careful then this can cause a mess.

Thats just a suggestion; I'm not sure if thats exactly how it works in PHP but I know it does happen in some languages.

Re: Switching the order of XML children

Posted: Fri Feb 20, 2009 12:48 am
by Still Learning
If that's the case, how could that be avoided? Introduction of another variable and setting the value equal to the previous? I'd think that would still give the same result.

You'd think with a parser called "Simple XML" that there would be a simple way to swap values of what's contained in the XML files. I"ve checked and haven't found any pre-made functions to do this.


PLZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz......


someone with experience chime in. I'm seriously going crazy at this point. This seems like such a simple script to write but everything I try is an epic fail. :banghead:

Re: Switching the order of XML children

Posted: Fri Feb 20, 2009 3:59 am
by Weirdan
Still Learning wrote:If that's the case, how could that be avoided? Introduction of another variable and setting the value equal to the previous?

Code: Select all

 
$a = new stdClass;
$b = new stdClass;
 
$c = $a; // $a and $c point to the same object, you have two objects in total
$c = clone $a; // $a points to original object, $c points to the copy of it, you have three objects in total
 

Re: Switching the order of XML children

Posted: Fri Feb 20, 2009 12:27 pm
by Still Learning
Weirdan wrote:
Still Learning wrote:If that's the case, how could that be avoided? Introduction of another variable and setting the value equal to the previous?

Code: Select all

 
$a = new stdClass;
$b = new stdClass;
 
$c = $a; // $a and $c point to the same object, you have two objects in total
$c = clone $a; // $a points to original object, $c points to the copy of it, you have three objects in total
 

OMG thank you so much!!!

I finally have it working. That solved the problem.