Page 1 of 1

Can't append to xml

Posted: Fri Apr 23, 2010 11:03 pm
by CrazyEight
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

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

Re: Can't append to xml

Posted: Sat Apr 24, 2010 12:42 pm
by John Cartwright
Admitely, you posted a lot of code and do not have the time to carefully look at it... however... at a quick glance I can see you probably want this line (in your save_xml function

Code: Select all

if ($type_of_save == "overwrite")
{
to be

Code: Select all

if ($type_of_save == "append")
{
Is there any reason your not using simplexml?