This post has been moved to my technical blog.

Direct link : http://abstraction.blog/2010/09/04/php-xml-create-add-edit-modify-using-dom-simplexml-xpath


Advertisements

42 thoughts on “PHP : XML Create-Add-Edit-Modify using DOM , SimpleXML , XPath

  1. Example 9 doesn’t work for me, it outputs:

    Ayn Rand
    300

    J.R.R.Tolkein
    500

    Stephen King
    200

    It appears that the changes aren’t updated.

    1. Good Catch.
      DOM Code Rectified so as to reflect appropriate XML indices.
      SimpleXML code changed so as to depend on DOM now since earlier code wouldn’t work for CDATA section.

      1. Thanks this works perfectly, where did you find the information about DOM’s XML indices? I would like to read up on that.

        I’ve been looking to do reordering of XML elements on and off for 4 years now. Thanks again!

  2. Discovered it quite a while back when I was practicing with XML DOM. Index 0 is tied to a blank text node while Index 1 points to the XML node (1st book) & so on alternatively. Had forgotten abt it since SimpleXML doesn’t have it.

    1. You are welcome. I can understand your situation…went through the same last year…hence decided to do something about it. Glad it was of use to you 🙂

  3. Great examples ! That’s what I was looking for. Just one thing I’m struggling with, maybe you can help. My xml structure is hierarchical :
    http://pastebin.com/zGKShpgS .
    I need to find element by id so i use xpath->query(‘//item[@id=x]) , but now how can I appendChild after or before this element ? I’d thought it would be as simple as $library->insertBefore($newitem,$xpathresult), but it doesn’t seem to work. Any ideas ?

  4. Hi there I got question:

    I am trying to edit below table.xml file using php base on the result.xml but your solution did not work for me. can you help me please.

    table.xml

    Man U
    1
    0
    0
    1
    0
    0

    Chelsea
    0
    0
    0
    0
    0
    o

    LiverPool
    1
    1
    0
    0
    0
    3

    Arsenal
    1
    0
    1
    0
    0
    1

    and result.xml

    Results

    Man u
    6

    Chelsea
    0

    .
    .
    .

    thanks

  5. Here is the details what exactly I am trying to do:

    read the result.xml file
    then compare with team name with table.xml
    if team name match with result.xml

    update record in table.xml
    for home team
    update no of match played +1
    update points on the base of goal (6-0)

    for away team
    update no of match played +1
    update points on the base of goal (0-6)

    hope you got it now

    1. Not sure if I understood your xml structure…cause the numbers don’t make sense…do they represent goals scored or points achieved ? why don’t you mention the proper xml with the node names instead of just the values.
      As far as I can understand, you plan to use the result.xml file to update the table.xml file using the club name as the search parameter. The “(3) Edit XML – Edit specific Elements (accessed conditionally)” eg should help you to find the club name (assuming its an attribute value).

  6. here is my xml file
    table.xml

    Man U
    1
    0
    0
    1
    0
    0

    Chelsea
    0
    0
    0
    0
    0
    o

    LiverPool
    1
    1
    0
    0
    0
    3

    Arsenal
    1
    0
    1
    0
    0
    1

    result.xml

    Man U
    6

    Chelsea
    0

    .
    .
    .
    .
    .
    .

    hope you will be able to help.

  7. result.xml file:

    
    <?xml version="1.0"?>
                          <results>
                                   <result id="6548">
                                           <hometeam>
                                                     <name>Man U</name>
                                                     <score>6</score>
                                           </hometeam>
                                           <awayteam>
                                                     <name>Chelsea</name>
                                                     <score>0</score>
                                           </awayteam>
                                   </result>
                                   <result id="6548">
                                   .
                                   .
                                   .
                                   .
                                   .
                                   .
                                    </result>
    
                          </results>
    

    table.xml

    <?xml version="1.0" encoding="iso-8859-1"?>
    <Teams>
      <Team>
        <name>Man U</name>
        <Played>1</Played>
        <Won>0</Won>
        <Drawn>0</Drawn>
        <Lost>1</Lost>
        <GoalDif>0</GoalDif>
        <Points>0</Points>
      </Team>
      <Team>
        <name>Chelsea</name>
        <Played>0</Played>
        <Won>0</Won>
        <Drawn>0</Drawn>
        <Lost>0</Lost>
        <GoalDif>0</GoalDif>
        <Points>o</Points>
      </Team>
      <Team>
        <name>LiverPool</name>
        <Played>1</Played>
        <Won>1</Won>
        <Drawn>0</Drawn>
        <Lost>0</Lost>
        <GoalDif>0</GoalDif>
        <Points>3</Points>
      </Team>
      <Team>
        <name>Arsenal</name>
        <Played>1</Played>
        <Won>0</Won>
        <Drawn>1</Drawn>
        <Lost>0</Lost>
        <GoalDif>0</GoalDif>
        <Points>1</Points>
      </Team>
    </Teams>
    

    hope you will be able to help.

    1. Sorry I couldn’t reply earlier….bunch of stuff kept me busy.
      Built a sample solution in which we read from result.xml & edit the played element of table.xml :

      function fnDOMEditElementSeq()
      {
          
          $domTable = new DOMDocument();
          $domTable->load('table.xml');    
          $xpath = new DOMXPath($domTable);
      
          $domResult = new DOMDocument();
          $domResult->load('result.xml');
          
          $results = $domResult->documentElement;
          $cnt = $results->childNodes->length;
          for($iter = 0; $iter < $cnt; $iter++) {
              $result = $results->getElementsByTagName('result')->item($iter);
              $teamName = $result->getElementsByTagName('hometeam')->item(0)->getElementsByTagName('name')->item(0)->nodeValue;
              if ($teamName) {
                  $searchResult = $xpath->query('/Teams/Team[name="' .$teamName.'"]');
                  $searchResult->item(0)->getElementsByTagName('Played')->item(0)->nodeValue += 1;            
              }        
          }    
          // To display the xml;
          //header("Content-type: text/xml");
          //echo $domTable->saveXML();
          
          $domTable->save('table.xml');
      }
      
      1. Thank you very much for your help, but function did not work with me, sorry to bother you again, have you tested the function.? Hope you will get back to me when you got time. thanks.

      2. Here is the error:
        Fatal error: Call to a member function getElementsByTagName() on a non-object in C:\dev\www\read.php on line 17

        
        if ($teamName) {
                    $searchResult = $xpath->query('/Teams/Team[name="' .$teamName.'"]');
                    $searchResult->item(0)->getElementsByTagName('Played')->item(0)->nodeValue += 1;
                }
        

        which is pointing last line of if statement, can you please have a look. thanks

      3. $domTable = new DOMDocument();
            $domTable->load('LeagueTable.xml');
            $xpath = new DOMXPath($domTable);
        
            $domResult = new DOMDocument();
            $domResult->load('result.xml');
        
            $results = $domResult->documentElement;
            $cnt = $results->childNodes->length;
            $homeTeamName ='';
            $awayTeamName ='';
            $homeScore =0;
            $AwayScore =0;
            $homePoints =0;
            $awayPoints =0;
            $homeWon =0;
            $awayWon =0;
            $homeLost =0;
            $awayLost =0;
            $howDrawn =0;
            $awayDrawn =0;
        
            for($iter = 0; $iter < $cnt; $iter++) {
                $result = $results->getElementsByTagName('result')->item($iter);
                $homeTeamName = $results->getElementsByTagName('hometeam')->item(0)->getElementsByTagName('name')->item(0)->nodeValue;
                $homeScore = $results->getElementsByTagName('hometeam')->item(0)->getElementsByTagName('score')->item(0)->nodeValue;
                $awayTeamName = $results->getElementsByTagName('awayteam')->item(0)->getElementsByTagName('name')->item(0)->nodeValue;
                $AwayScore = $results->getElementsByTagName('awayteam')->item(0)->getElementsByTagName('score')->item(0)->nodeValue;
        
            }
                if($homeScore - $AwayScore >=1)
                {
                   $homePoints =3;
                   $awayPoints =0;
                   $homeWon =1;
                   $awayLost =1;
        
        
                }
                elseif($homeScore - $AwayScore =0)
                {
                   $homePoints =1;
                   $awayPoints =1;
                   $howDrawn =1;
                   $awayDrawn =1;
                }
                 else
                 {
                    $homePoints =0;
                    $awayPoints =3;
                    $homeLost =1;
                    $awayWon =1;
                 }
        
                if ($homeTeamName) {
                    $searchResult = $xpath->query('/Teams/Team[Name="' .$homeTeamName.'"]');
                    $searchResult->item(0)->getElementsByTagName('Played')->item(0)->nodeValue += 1;
                    $searchResult->item(0)->getElementsByTagName('Points')->item(0)->nodeValue += $homePoints;
                    $searchResult->item(0)->getElementsByTagName('GoalDif')->item(0)->nodeValue += $homeScore - $AwayScore;
                    $searchResult->item(0)->getElementsByTagName('Won')->item(0)->nodeValue += $homeWon;
                    $searchResult->item(0)->getElementsByTagName('Lost')->item(0)->nodeValue += $homeLost;
                    $searchResult->item(0)->getElementsByTagName('Drawn')->item(0)->nodeValue += $homeDrawn;
        
                }
                if ($awayTeamName) {
                    $searchResult = $xpath->query('/Teams/Team[Name="' .$awayTeamName.'"]');
                    $searchResult->item(0)->getElementsByTagName('Played')->item(0)->nodeValue += 1;
                    $searchResult->item(0)->getElementsByTagName('Points')->item(0)->nodeValue += $awayPoints;
                    $searchResult->item(0)->getElementsByTagName('GoalDif')->item(0)->nodeValue += $AwayScore - $homeScore;
                     $searchResult->item(0)->getElementsByTagName('Won')->item(0)->nodeValue += $awayWon;
                    $searchResult->item(0)->getElementsByTagName('Lost')->item(0)->nodeValue += $awayLost;
                    $searchResult->item(0)->getElementsByTagName('Drawn')->item(0)->nodeValue += $awayDrawn;
        
                }
        
            //To display the xml;
            header("Content-type: text/xml");
            echo $domTable->saveXML();
        
            $domTable->save('LeagueTable.xml');
        
        
        ?>
        

        hi there, i have modified your code and end the for loop before if statement becouse loop goes round 3 time with the tags (, and ) as result played add up 3 times. it work fine but i cant read more then one result, can you please have a look the code i have modified?? thank you in advance.

    1. Hi, I am looking for something similar, its part of my assignment in college. Could you please help me if possible. It would be great help. I would immensely appreciate if you could mail it to me. My email id is sanjyot_31@yahoo.com

  8. hi there, i was try to learn about php and xml but when i tried to cek, update, and create i got stuck, maybe you can help me out with this snippet

    load(‘server.xml’);
    $dashboard_xpath = new DOMXPath($dashboard_xml);
    $dashboard_query = $dashboard_xpath->query(‘/Dashboard/Server[@id=1]’);
    $dashboard_result = false;
    foreach($dashboard_query as $dashboard_result){
    if($dashboard_result){
    // Update XML FIle Elements;
    } else {
    // Create XML Elements;
    }
    }
    ?>

    172.17.2.71
    80
    3306

    172.17.2.71
    21
    80

    i was googling all day long but still nothing, wish you can help me out with a bit example or direct we to a good tuts web, really thanks before.

  9. Hi,
    dom_import_simplexml is not working when i tried for Reorder of elements in XML.

    I am getting empty array.

    Let me know what will be the problem.

    $libSimple= new SimpleXMLElement(‘library.xml’,null,true); // getting Simplexmlelement
    $libDom = dom_import_simplexml($libSimple); // Empty array is the output for this line.

    Thanks,
    Prakash Mukta

    1. dom_import_simplexml is an inbuilt function.
      It will always work provided the xml file is proper.

      Btw thx to your comment, I just checked the code & found an issue in the reordering of elements when the elements are not alongside each other.
      The issue is fixed now !

  10. Good afternoon,
    How would I do if my xml was cascading?

    eg

    
    
      
        
        Ayn Rand
        300
    		  
    			
    			J.R.R.Tolkein
    			500
    				  
    					
    					Stephen King
    					200
    
    					
    						//1004A - NEW 
    						  
    							
    							Stephen King
    							200
    						  
    						  
    						//1004B - OLD 
    						  
    							
    							Stephen King
    							200
    						  
    				  
    		  
      
    
    
  11. Hello, I am trying to append an XML file and i should save new elements to the xml file, information taken from textboxes. But unfortunately after trying some of your codes i am unable to write the my xml file.

    Could you please help.

  12. Hi Thank you for this tutorial, soo so helpful,
    The code is working fine on the browser but not saving the changes to the file and no thing change in the xml file?

  13. (2) Edit XML – Edit/Modify Element Data (accessed serially)
    part (ii) DOM – not working for me.

    $cnt = $library->childNodes->length; // $cnt return 7 !??? not 2 – it is 3 books
    $library->childNodes->item($cnt-1)->getElementsByTagName(‘title’)->item(0)->nodeValue .= ‘ Series’;
    == Fatal error: Call to undefined method DOMText::getElementsByTagName() …

  14. foreach($library->childNodes as $node){
    echo $node->nodeName.’ – ‘.$node->nodeValue, “”;
    }
    // it is list 7 childrens & values 😦
    /*
    #text –
    book – The Fountainhead Ayn Rand 300
    #text –
    book – The Lord of the Rings J.R.R.Tolkein 500
    #text –
    book – The Dark Tower Stephen King 200
    #text –

  15. Hello congratulations for your article.
    I used the codes, I created a file library.xml and lib.php where I copied the inside:
    // (I) SimpleXML
    // Edit Last Book Title
    fnSimpleXMLEditElementSeq function ()
         {
             $ library = new SimpleXMLElement (‘library.xml’, null, true);
             $ num = count ($ library);
             $ library-> book [$ num-1] -> title. = ‘- The Gunslinger’;
             header (“Content-type: text / xml”);
             echo $ library-> asXml ();
         }

    But unfortunately it does not work, where am I wrong? as the function is called or what parameters I have to pass?

    Thank you and congratulations for the work done.

  16. I think for append record before you have wrong code as you have written

    header(“Content-type: text/xml”);
    echo $dom->saveXML();

    Instead of
    echo $dom->saveXML(); it should be
    echo $dom->save(‘library.xml’);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s