Can't append to xml
Posted: Fri Apr 23, 2010 11:03 pm
I am just about to give up trying to solve this. Here is my problem. I have these files that I need to append whatever the user enter in the html form and put it at the end of the file, using the 'id' index.
File #1 shows-content.php
code
Output:
current equipment list for company xyz are:
ID Model Department Status DateInstalled DateReplaced Cost
1 Network Printer XL234 IT Out of commission, ticket number on file. 15 May 2005 12 Dec 2007 $1200
2 xerox copier Sales Inactive, waiting for budget approval. 15 May 2000 27 Oct 2003 $1000
3 Linksys router Engineer Out of commission
File #1 shows-content.php
code
Code: Select all
<?php
// Echo our XML declaration to the browser. This must be done with an
// echo statement within PHP because otherwise the PHP processor on the
// server will treat the starting <? as the beginning of a PHP block
// instead of an XML block.
echo '<?xml version="1.0" encoding="UTF-8" ?>';
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Accessing and Saving XML Files</title>
<?php
// Create an array to hold the new objects when loaded from the XML data file.
$input_array = array();
// Load the PHP file that defines our classes.
require "define-classes.php";
// Load the PHP file that has code to read the XML data file and convert it
// to a PHP object that we can then use when we build the xhtml content the
// browser will be sent.
require "load-xml.php";
// Load the PHP file that has code to save the data from an array of
// objects into an XML data file. This is how you output your changed
// objects.
require "save-xml.php";
// Read in the data from an XML file by calling the parse_xml_file function.
// The function will convert the XML data into PHP objects of the appropriate
// class, and add them to the array called $input_array. When calling
// the parse_xml_file() function, you must provide two parameters. First,
// specify the name of the file that has the XML data. Second, specify the
// name or tag used for the objects you wish to load from that file. For
// example, if the contents of the file are organized in <product> tags,
// and they will therefore be converted into objects of the class "product",
// specify "product" in the second parameter.
parse_xml_file( "equipments.xml", "equipment" );
// You can call the function save_xml() to output an array of objects into
// a file in XML format. The function requires three arguments.
// The first argument should be the name of the PHP array to save.
// The second argument is the name of the XML file to save the content in.
// The third argument should be either "overwrite" or "append", depending on
// whether you wish to replace the existing file with just the contents
// of the current array, or if you want to add the contents of the current
// array to the end of the existing file.
// ------------------------------------------------------------------------
// PLEASE NOTE: You only have to call this function if you have made
// changes to the contents of the array and wish to save those contents
// in your XML file. If you have just read in the XML file and displayed
// its contents, you do NOT need to use this function.
// ------------------------------------------------------------------------
save_xml( $input_array, "equipments.xml", "append" );
?>
</head>
<body>
<h1>Augusto's Equipment control website</h1>
<h2>The current equipment list for company xyz are:</h2>
<form>
<INPUT TYPE="button" VALUE="New Entry" ONCLICK="window.location.href='http://www2.esc.edu/asarino/equipmentEntry1.html'">
</form>
<table border="1" width="100%">
<tr>
<th style="width: 50px">ID</th>
<th style="width: 150px">Model</th>
<th>Department</th>
<th>Status</th>
<th>DateInstalled</th>
<th>DateReplaced</th>
<th>Cost</th>
</tr>
<?php
// Add a row to the table for each of the existing products, outputing its properties in table cells.
foreach ($input_array as $current_object)
{
?>
<tr>
<td><?php echo $current_object->id ?></td>
<td><?php echo $current_object->model ?></td>
<td><?php echo $current_object->department ?></td>
<td><?php echo $current_object->status ?></td>
<td><?php echo $current_object->dateinstalled ?></td>
<td><?php echo $current_object->datereplaced ?></td>
<td><?php echo $current_object->cost ?></td>
<td><?php
?>
</td>
</tr>
<?php
}
?>
</table>
</body>
</html>
File#2 save-xml.php
code:
<?php
// You can call the function save_xml() to output an array of objects into
// a file in XML format. The function requires three arguments.
// The first argument should be the name of the PHP array to save.
// The second argument is the name of the XML file to save the content in.
// The third argument should be either "overwrite" or "append", depending on
// whether you wish to replace the existing file with just the contents
// of the current array, or if you want to add the contents of the current
// array to the end of the existing file.
function save_xml ($object_array, $filename, $type_of_save)
{
// if you are appending data, open the existing file and remove the
// closing root tag so that more data objects can be appended.
if ($type_of_save == "overwrite")
{
// read in the old contents as a single string
$old_file_contents = file_get_contents($filename);
if (!$old_file_contents)
{
die("Error opening file $filename!");
}
// find the position of the closing root tag, and if found,
// make a substring starting at the beginning and ending
// before the closing root tag, then output it back to the file.
$end_tag_position = strpos( $old_file_contents, "</$filename>");
if (!$end_tag_position === false)
{
$new_file_contents = substr( $old_file_contents, 0, $end_tag_position );
file_put_contents($filename, $new_file_contents);
}
// re-open the file to append new content.
$fp = fopen($filename, "a+b");
if (!$fp) { die("Error opening file $filename."); }
}
else
{
// if the type_of_save is not append, open the file and overwrite it.
$fp = fopen($filename, "w+b");
if (!$fp) { die("Error opening file $filename."); }
// output the XML declaration and the opening root element tag.
write_line($fp, "<?xml version=\"1.0\"?>\n\n");
write_line($fp, "<$filename>\n");
}
// output the array objects to the file, using the writeXML method of the class.
foreach ($object_array as $current_object)
{
write_line($fp, $current_object->writeXML());
}
// output the closing root tag
write_line($fp, "\n</$filename>");
fclose($fp);
}
// This function writes the content to the specified file, and provides
// an error message if the operation fails.
function write_line ($fp, $line)
{
if (!fwrite($fp, $line))
die ("Error writing to file!");
}
// The function file_put_contents from the PHP web site does not exist
// in our server's version of PHP. This creates it.
if (!function_exists('file_put_contents'))
{
define('FILE_APPEND', 1);
function file_put_contents($filename, $content, $flags = 0)
{
if (!($file = fopen($filename, ($flags & FILE_APPEND) ? 'a' : 'w')))
return false;
$n = fwrite($file, $content);
fclose($file);
return $n ? $n : false;
}
}
?>
File#3 load-xml.php
code:
<?php
// The parse_xml_file function is used to read in an XML file and convert the XML data
// into an array of PHP objects. The function requires two parameters: the filename of
// the XML data file, and the exact tag used in that XML file for each of the XML object
// elements.
function parse_xml_file( $filename, $xml_object_tag )
{
// Read the XML file into a string variable.
$data = implode("", file($filename));
// Create the XML parser, set it to ignore white spaces like tabs and carriage returns,
// and set it to be case-insensitive.
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
// Convert the data string into two arrays. The array $xml_contents will contain each
// element in the XML file. The array $tag_index will be an associative array organized by
// tag names with a list of the indexes where that tag occurs.
xml_parse_into_struct($parser, $data, $xml_contents, $index);
// Free up server resources by closing the parser.
xml_parser_free($parser);
// Pull out the index array for just the object tag specified as a parameter to this function.
// This array will have the index for just the elements in the XML file with the specified
// object tag.
$xml_object_index_array = $index[$xml_object_tag];
// Loop through all the instances of that object tag, looking for each start tag.
foreach ($xml_object_index_array as $occurence=>$tag_index)
{
// If the current tag is a start tag, process this as an object.
if ($xml_contents[$tag_index]["type"] == "open")
{
// Store the start index for this object.
$xml_object_start_index = $tag_index;
// Loop through the remaining instances of the object tag to find the next closing tag.
$next_occurence = $occurence;
do
{
$next_occurence = $next_occurence+1;
$xml_object_end_index = $xml_object_index_array[$next_occurence];
}
while ($xml_contents[$xml_object_end_index]["type"] != "close");
// Convert the object from XML into a PHP object.
parse_xml_object($xml_contents, $xml_object_start_index, $xml_object_end_index, $xml_object_tag );
}
else // If the current tag isn't a start tag, go to the next iteration of the loop.
{
continue;
}
}
}
// The function "parse_xml_object" is used to create one instance, or object, of a PHP class,
// and then updates the properties of that object with the contents of the sub-elements in
// the XML object. It does this by looking in the array of all tags from the XML document,
// starting at the specified start-index for the current object and ending at the closing
// tag for that object.
function parse_xml_object ( $xml_contents, $xml_object_start_index, $xml_object_end_index, $xml_object_tag )
{
global $input_array;
// Get the object_id property from the "id" attribute of the object tag in the XML file.
$object_id = $xml_contents[$xml_object_start_index]["attributes"]["id"];
// Create a new instance of the class, using the id property as the $input_array index.
$input_array[$object_id] = new $xml_object_tag ( $object_id );
// Loop through the remaining tags in the XML object, and set the PHP object's properties.
for ($i=$xml_object_start_index; $i <= $xml_object_end_index; $i++)
{
if ($xml_contents[$i]["type"] == "complete")
{
$input_array[$object_id]->addData($xml_contents[$i]["tag"], $xml_contents[$i]["value"]);
}
}
}
File#4 equipments.xml
code:
<?xml version="1.0" ?>
- <equipments.xml>
- <equipment id="1">
<model>Network Printer XL234</model>
<department>IT</department>
<status>Out of commission, ticket number on file.</status>
<dateinstalled>15 May 2005</dateinstalled>
<datereplaced>12 Dec 2007</datereplaced>
<cost>$1200</cost>
</equipment>
- <equipment id="2">
<model>xerox copier</model>
<department>Sales</department>
<status>Inactive, waiting for budget approval.</status>
<dateinstalled>15 May 2000</dateinstalled>
<datereplaced>27 Oct 2003</datereplaced>
<cost>$1000</cost>
</equipment>
- <equipment id="3">
<model>Linksys router</model>
<department>Engineer</department>
<status>Out of commission, ticket number is on file</status>
<dateinstalled>25 Aug 2005</dateinstalled>
<datereplaced>11 Sept 2007</datereplaced>
<cost>$1250</cost>
</equipment>
</equipments.xml>
File#5 EquipmentEntry1.html
code:
<html>
<head><title>Augusto CMS</title></head>
</head>
<form name="input" action="save-xml.php" method="post">
<fieldset><legend>Equipment entry form</legend>
<label for="model">Model:</label>
<input type="text" id="model" name="model" tabindex="1" /><br/><br />
<label for="department">Department:</label>
<input type="text" id="department" name="department" tabindex="2" /><br/><br />
<label for="status">Status:</label>
<input type="text" id="status" name="status" tabindex="3" /><br/><br />
<label for="dateinstalled">DateInstalled:</label>
<input type="text" id="dateinstalled" name="dateinstalled" tabindex="4" /><br/><br />
<label for="datereplaced">DateReplaced:</label>
<input type="text" id="datereplaced" name="datereplaced" tabindex="5" /><br/><br />
<label for="cost">Cost:</label>
<input type="text" id="cost" name="cost" tabindex="6" /><br/><br />
<input type="submit" value="send"/>
</form>
</body>
</html>
Output:
current equipment list for company xyz are:
ID Model Department Status DateInstalled DateReplaced Cost
1 Network Printer XL234 IT Out of commission, ticket number on file. 15 May 2005 12 Dec 2007 $1200
2 xerox copier Sales Inactive, waiting for budget approval. 15 May 2000 27 Oct 2003 $1000
3 Linksys router Engineer Out of commission