Solved

XML PHP |> Edit a xml file using php?

Posted on 2003-12-03
12
2,435 Views
Last Modified: 2013-11-19
Hey all,

Does someone know how to edit and add data into a xml file using php and xpath?

xml file:

<sessions>
      <session id="Dei6fB-mat792-uMPlte" username="vincent" password="xml"/>
</sessions>

thnx
0
Comment
Question by:dennebom
  • 7
  • 5
12 Comments
 
LVL 6

Expert Comment

by:PeterCiuffetti
ID: 9869634

You can extend your PHP installation to give it DOM editing functions.  The extension makes use of the GNOME XML library at http://www.xmlsoft.org/.  On my Win2000 machine, I have downloaded and installed libxml2-2.6.2, placing libxml2.dll in my winnt/system32 directory.

And then enabled the extension in php.ini (by just uncommenting the line already there)

extension=php_domxml.dll

I then needed to tell PHP about it by putting this in my Apache http.conf:
php_value with-dom "c:/winnt/system32/libxml2.dll"

Now I can read in an 'input.xml' file like the following:

<?xml version="1.0"?>
<myxml>
      <child no="1">This is the first child</child>
</myxml>

And then edit it with the folowing EditXml.php code

<?php
      /*
       * Example php code to read in, edit and write out an XML file
       */
      

      // Calculate the path of the input XML file      
      if ( $_SERVER["SERVER_PORT"] != 80 ) {
            $serverBasePath = "http://" . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . "/";
      }
      else {
            $serverBasePath = "http://" . $_SERVER["SERVER_NAME"] . "/";
      }
      $appPath = substr( $_SERVER["PHP_SELF"], 1, strrpos($_SERVER["PHP_SELF"],'/'));

      // Read the XML file into a DOM object
      if(!$dom = domxml_open_file($serverBasePath . $appPath . "input.xml")) {
        echo "Error while parsing the document" . $serverBasePath . $appPath . "input.xml\n";
        exit;
      }

      // Echo the original document      
      print "<h1>Original document</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";

      // Get the root of the document
      $root = $dom->document_element();

      // Create an XML element and a text node
      $newElem = $dom->create_element("new");
      $text = $dom->create_text_node("This is the new contents added");

      // Set the XML attribute to the new element
      $newElem->set_attribute("myAttr", "new attribute value");

      // Add the text node to the new element
      $text = $newElem->append_child($text);

      // Append the new element to the document (child of the root)
      $root = $root->append_child($newElem);
            
      // Write out the modified document to a file
      $dom->dump_file("/temp/output.xml", false, true);

      // Echo the modified document
      print "<h1>Modified document</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";
            
?>

This will produce a /temp/output.xml with the following:

<?xml version="1.0"?>
<myxml>
      <child no="1">This is the first child</child>
<new myAttr="new attribute value">This is the new contents added</new></myxml>

0
 

Author Comment

by:dennebom
ID: 9882486
OK, thnx!!

Offcourse it didn't work!! But with a few ajustments, now it works!!

I changes this:

// Write out the modified document to a file
$fp = fopen($session_xml, "w+" );
fwrite($fp, $dom->dump_mem(true));
fclose($fp);

But this function only add's node's to my xml file!!! How can I delete and edit a node from the xml file??????

If I got the answer for edit and delete you got your 500 point!!!!

dennebom
0
 
LVL 6

Expert Comment

by:PeterCiuffetti
ID: 9883741
Here is an example that demonstrates editing (which is a process of replacing nodes) and node removal.  Again my sample input.xml was this:

<?xml version="1.0"?>
<myxml>
      <child no="1">This is the first child</child>
</myxml>



<?php
      /*
       * Example php code to read in, edit and write out an XML file
       */
      

      // Calculate the path of the input XML file      
      if ( $_SERVER["SERVER_PORT"] != 80 ) {
            $serverBasePath = "http://" . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . "/";
      }
      else {
            $serverBasePath = "http://" . $_SERVER["SERVER_NAME"] . "/";
      }
      $appPath = substr( $_SERVER["PHP_SELF"], 1, strrpos($_SERVER["PHP_SELF"],'/'));

      // Read the XML file into a DOM object
      if(!$dom = domxml_open_file($serverBasePath . $appPath . "input.xml")) {
        echo "Error while parsing the document" . $serverBasePath . $appPath . "input.xml\n";
        exit;
      }

      // Echo the original document      
      print "<h1>Original document</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";

      // Get the root of the document
      $root = $dom->document_element();

      // Create an XML element and a text node
      $newElem = $dom->create_element("new");
      $text = $dom->create_text_node("This is the new contents added");

      // Set the XML attribute to the new element
      $newElem->set_attribute("myAttr", "new attribute value");

      // Add the text node to the new element
      $text = $newElem->append_child($text);

      // Append the new element to the document (child of the root)
      $root->append_child($newElem);
            
      // Echo the modified document
      print "<h1>New element added to document</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";
      
      // Change the text in the child node of the original document
      $text = $dom->create_text_node("This contents replaces the original text node in child");
      $root = $dom->document_element();
      $children = $root->get_elements_by_tagname("child");

      // Set the text node that is the child of children[0]
      $child = $children[0]->first_child();
      $child->replace_node($text);
            
      // Echo the modified document
      print "<h1>Old text element replaced</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";
      
      // Remove the original element
      $root = $dom->document_element();
      $children = $root->get_elements_by_tagname("child");
      $root->remove_child($children[0]);
      // Echo the modified document
      print "<h1>Original child element removed</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";
      
      
      // Write out the modified document to a file
      $dom->dump_file("/temp/output.xml", false, true);

?>

For simplicity, I've left out all the error checking, but normally you would check the boolean return values from each dom operation to make sure you were getting the expected node.  The has_child_nodes() and has_attribute() functions can tell you whether the part of the DOM you are looking at has any content.

Other functions are also useful in editing such as clone_node(), insert_before(), append_child(), replace_child(), append_sibling().  See http://us2.php.net/manual/en/ref.domxml.php for further functions available.

And if the kind of editing you want to do is repetitive, then it might help to process the DOM with an XSLT stylesheet.  This can perform the same function on all elements with a given name (and many other sohpisticated modifications).  XSLT processing in PHP also requires enabling the extension.

0
 

Author Comment

by:dennebom
ID: 9895395
thnx for thw post, but i'm still stuck!!!

this is the xml file that i want to edit.

<?xml version="1.0"?>
<sessions>
      <session id="ylgeo8-i8ckau-74wi9b"
                              username="full"
                              password="xml"
                              groupname="administrator"
                              userid=""
                              groupid=""
                              date="200312041158"
                              localip="192.168.7.51"
                              remoteip="192.168.7.51"/>
 </sessions>

When my page reloades then the date has to be set again. So I want to change the date in this xml file. But how????????????????
0
 

Author Comment

by:dennebom
ID: 9896098
and i've got an error with editing:

Fatal error: Call to a member function on a non-object in

that revers to this section of the edit code:

            // Set the text node that is the child of children[0]
            $child = $children[0]->first_child();
            $child->replace_node($text);
0
 
LVL 6

Expert Comment

by:PeterCiuffetti
ID: 9897330
Hi,

You need to understand that when the input is different, the paths to (and names of) the elements and the attributes in the DOM change.   Also, the functions used to change, add or delete elements is different than the functions used to change add or delete attributes.  My code worked for my input, it would need to change for your input.  The code below changes the date attribute in the first session element.

<?php
      /*
       * Example php code to read in, edit and write out an XML file
       */

      // Calculate the path of the input XML file      
      if ( $_SERVER["SERVER_PORT"] != 80 ) {
            $serverBasePath = "http://" . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . "/";
      }
      else {
            $serverBasePath = "http://" . $_SERVER["SERVER_NAME"] . "/";
      }
      $appPath = substr( $_SERVER["PHP_SELF"], 1, strrpos($_SERVER["PHP_SELF"],'/'));

      // Read the XML file into a DOM object
      if(!$dom = domxml_open_file($serverBasePath . $appPath . "input.xml")) {
        echo "Error while parsing the document" . $serverBasePath . $appPath . "input.xml\n";
        exit;
      }

      // Echo the original document      
      print "<h1>Original document</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";

      // Change the date attribute in the first session node of the original document
      $root = $dom->document_element();
      $children = $root->get_elements_by_tagname("session");
      $child = $children[0];
      $child->set_attribute("date", date("Ymdhm"));
            
      // Echo the modified document
      print "<h1>Old date attribute replaced</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";
      
      // Write out the modified document to a file
      $dom->dump_file("/temp/output.xml", false, true);

?>

The produces the following output:

Original document
<?xml version="1.0"?>
<sessions>
     <session id="ylgeo8-i8ckau-74wi9b" username="full" password="xml" groupname="administrator" userid="" groupid="" date="200312041158" localip="192.168.7.51" remoteip="192.168.7.51"/>
</sessions>

Old date attribute replaced
<?xml version="1.0"?>
<sessions>
     <session id="ylgeo8-i8ckau-74wi9b" username="full" password="xml" groupname="administrator" userid="" groupid="" date="200312081112" localip="192.168.7.51" remoteip="192.168.7.51"/>
</sessions>

0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:dennebom
ID: 9902628
Can I remove or edit child by define the session id instead off using the following:
 $child = $children[0];

Now it counts witch index he has te edit or remove. I want that he edit or delete the session by pointing add the session id.

again thnx.

I already gave you the points because you helped me out. THNX!!!!
0
 

Author Comment

by:dennebom
ID: 9902635
Sorry i can't give you the point yet!! Otherwise the question will be closed. But you will get them!!
0
 
LVL 6

Expert Comment

by:PeterCiuffetti
ID: 9904296
You can pass in the id as a querystring parameter, and then look for the session with that id.  I.e.

<?php
      /*
       * Example php code to read in, edit and write out an XML file
       */

      $sessionid = $_GET["sessionid"] or $sessionid = "xxx";

      // Calculate the path of the input XML file      
      if ( $_SERVER["SERVER_PORT"] != 80 ) {
            $serverBasePath = "http://" . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . "/";
      }
      else {
            $serverBasePath = "http://" . $_SERVER["SERVER_NAME"] . "/";
      }
      $appPath = substr( $_SERVER["PHP_SELF"], 1, strrpos($_SERVER["PHP_SELF"],'/'));

      // Read the XML file into a DOM object
      if(!$dom = domxml_open_file($serverBasePath . $appPath . "input.xml")) {
        echo "Error while parsing the document" . $serverBasePath . $appPath . "input.xml\n";
        exit;
      }

      // Echo the original document      
      print "<h1>Original document</h1>";
      echo "<pre>";
      echo htmlentities($dom->dump_mem(true));
      echo "</pre>";

      // Change the date attribute in the session node of the original document
      $root = $dom->document_element();
      if ( $children = $root->get_elements_by_tagname("session") ) {
            foreach ($children as $child)
            {
                  if ( $child->get_attribute("id") == $sessionid ) {
                        $child->set_attribute("date", date("Ymdhi"));
                  }
            }
                  
            // Echo the modified document
            print "<h1>Old date attribute replaced</h1>";
            echo "<pre>";
            echo htmlentities($dom->dump_mem(true));
            echo "</pre>";
            
            // Write out the modified document to a file
            $dom->dump_file("/temp/output.xml", false, true);
      } else {
            print "<b>No sessions in the input.xml file</b>";
      }

?>

Given an input.xml document like this:

<?xml version="1.0"?>
<sessions>
     <session id="ylgeo8-i8ckau-74wi9a" username="one" password="xml" groupname="administrator" userid="1" groupid="1" date="200312011158" localip="192.168.7.51" remoteip="192.168.7.51"/>
     <session id="ylgeo8-i8ckau-74wi9b" username="two" password="xml" groupname="administrator" userid="2" groupid="1" date="200312021158" localip="192.168.7.52" remoteip="192.168.7.52"/>
     <session id="ylgeo8-i8ckau-74wi9c" username="three" password="xml" groupname="administrator" userid="3" groupid="1" date="200312031158" localip="192.168.7.53" remoteip="192.168.7.53"/>
</sessions>


The following URL: http://localhost/Test/EditXml.php?sessionid=ylgeo8-i8ckau-74wi9b, will produce

Original document
<?xml version="1.0"?>
<sessions>
     <session id="ylgeo8-i8ckau-74wi9a" username="one" password="xml" groupname="administrator" userid="1" groupid="1" date="200312011158" localip="192.168.7.51" remoteip="192.168.7.51"/>
     <session id="ylgeo8-i8ckau-74wi9b" username="two" password="xml" groupname="administrator" userid="2" groupid="1" date="200312021158" localip="192.168.7.52" remoteip="192.168.7.52"/>
     <session id="ylgeo8-i8ckau-74wi9c" username="three" password="xml" groupname="administrator" userid="3" groupid="1" date="200312031158" localip="192.168.7.53" remoteip="192.168.7.53"/>
</sessions>

Old date attribute replaced
<?xml version="1.0"?>
<sessions>
     <session id="ylgeo8-i8ckau-74wi9a" username="one" password="xml" groupname="administrator" userid="1" groupid="1" date="200312011158" localip="192.168.7.51" remoteip="192.168.7.51"/>
     <session id="ylgeo8-i8ckau-74wi9b" username="two" password="xml" groupname="administrator" userid="2" groupid="1" date="200312090922" localip="192.168.7.52" remoteip="192.168.7.52"/>
     <session id="ylgeo8-i8ckau-74wi9c" username="three" password="xml" groupname="administrator" userid="3" groupid="1" date="200312031158" localip="192.168.7.53" remoteip="192.168.7.53"/>
</sessions>

You can also try Xpath to select the session with the desired id, but those functions are not very well documented.  There is also a get_element_by_id function but I think that looks for ID= not id=.

0
 

Author Comment

by:dennebom
ID: 9911011
OK, now I tried to delete a specified session by using this function:

function DeleteSession($session_xml, $Session_dom, $SessionID) {

     $root = $Session_dom->document_element();
            
     if ( $children = $root->get_elements_by_tagname("session")){
      foreach ($children as $child)      {
            if ( $child->get_attribute("id") == $SessionID ) {
             $child->remove_child($children[$child]);   <====== THE PROBLEM!!
            }
      }
}

I used the script you just posted. But he gives a error offcourse :(

I hope you will help me again. I'm just a newbie, and you helped me out verry well
0
 
LVL 6

Accepted Solution

by:
PeterCiuffetti earned 500 total points
ID: 9912439
...this is becoming the question that never ends...

The problem with your code is that you are trying to get an element to remove itself.  The remove_child function allows a parent element to remove one of its children (the function name 'remove_child' gives this away).  Of course the PHP manual would say this except the documentation is abysmal.  Fortunately, most DOM implementations have similar functionality, so if you are familiar with, say, DOM operations in Java or C#, then you can understand how PHP DOM functions should operate.  If you look at the API for the org.w3c.dom package located here: http://java.sun.com/j2se/1.4.1/docs/api/index.html, you'll get a little more description on the various DOM functions in Java.  Or you can also study the DOM definition produced by the W3C at http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html.  This gives a generic description of each DOM function as well as an overview of the model.

Try this...

function DeleteSession($Session_dom, $SessionID) {

     $root = $Session_dom->document_element();
         
     if ( $children = $root->get_elements_by_tagname("session")){
          foreach ($children as $child)     {
               if ( $child->get_attribute("id") == $SessionID ) {
                    $root->remove_child($child);
               }
     }
}
0
 

Author Comment

by:dennebom
ID: 9918937
the question has come to an end!!!!!

I will thank you for al the answer's. You helped me out with al my problem's!!!!!!

dennebom
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
JQuery tracking event. 3 41
How to read XML file attributes... 17 42
XSL - change date format 3 29
Adjust the position 3 14
Many times as a report developer I've been asked to display normalized data such as three rows with values Jack, Joe, and Bob as a single comma-separated string such as 'Jack, Joe, Bob', and vice versa.  Here's how to do it. 
JavaScript has plenty of pieces of code people often just copy/paste from somewhere but never quite fully understand. Self-Executing functions are just one good example that I'll try to demystify here.
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now