xml = $xml;
// Set default values
$this->version = '1.0';
$this->encoding = "ISO-8859-1";
$this->dtd = '';
$this->entities = array();
$this->xml_index = array();
$this->xml_reference = 0;
$this->stack = array();
}
function parse() {
// Creates the object tree from XML code
$this->parser = xml_parser_create($this->encoding);
xml_set_object($this->parser, $this);
xml_set_element_handler($this->parser, "startElement", "endElement");
xml_set_character_data_handler($this->parser, "characterData");
xml_set_default_handler($this->parser, "defaultHandler");
if (!xml_parse($this->parser, $this->xml)) {
// Error while parsing document
$err_code = xml_get_error_code();
$err_string = xml_get_error_string();
$err_line = xml_get_current_line_number();
$err_col = xml_get_current_column_number();
$err_byte = xml_get_current_byte_index();
print "
Error Code: $err_code
$err_string
Line: $err_line
Column: $err_col
";
}
xml_parser_free($this->parser);
}
function generate() {
// Generates XML string from the xml_doc::document object
// Create document header
if ($this->version == '' and $this->encoding == '') {
$out_header = '<' . '?xml ?' . ">\n";
} elseif ($this->version != '' and $this->encoding == '') {
$out_header = '<' . "?xml version=\"{$this->version}\"?" . ">\n";
} else {
$out_header = '<' . "?xml version=\"{$this->version}\" encoding=\"{$this->encoding}\"?" . ">\n";
}
if ($this->dtd != '') {
$out_header .= "dtd . ">\n";
}
// Get reference for root tag
$_root =& $this->xml_index[0];
// Create XML for root tag
$this->xml = $this->createXML(0);
return $out_header . $this->xml;
}
function stack_location() {
// Returns index for current working tag
return $this->stack[(count($this->stack) - 1)];
}
function startElement($parser, $name, $attrs=array()) {
// Process a new tag
// Check to see if tag is root-level
if (count($this->stack) == 0) {
// Tag is root-level (document)
$this->document = new xml_tag($this,$name,$attrs);
$this->document->refID = 0;
$this->xml_index[0] =& $this->document;
$this->xml_reference = 1;
$this->stack[0] = 0;
} else {
// Get current location in stack array
$parent_index = $this->stack_location();
// Get object reference to parent tag
$parent =& $this->xml_index[$parent_index];
// Add child to parent
$parent->addChild($this,$name,$attrs);
// Update stack
array_push($this->stack,($this->xml_reference - 1));
}
}
function endElement($parser, $name) {
// Update stack
array_pop($this->stack);
}
function characterData($parser, $data) {
// Add textual data to the current tag
// Get current location in stack array
$cur_index = $this->stack_location();
// Get object reference for tag
$tag =& $this->xml_index[$cur_index];
// Assign data to tag
$tag->contents = $data;
}
function defaultHandler($parser, $data) {
}
function createTag($name, $attrs=array(), $contents='', $parentID = '') {
// Creates an XML tag, returns Tag Index #
if ($parentID === '') {
// Tag is root-level
$this->document = new xml_tag($this,$name,$attrs,$contents);
$this->document->refID = 0;
$this->xml_index[0] =& $this->document;
$this->xml_reference = 1;
return 0;
} else {
// Tag is a child
// Get object reference to parent tag
$parent =& $this->xml_index[$parentID];
// Add child to parent
return $parent->addChild($this,$name,$attrs,$contents);
}
}
function createXML($tagID,$parentXML='') {
// Creates XML string for a tag object
// Specify parent XML to insert new string into parent XML
$final = '';
// Get Reference to tag object
$tag =& $this->xml_index[$tagID];
$name = $tag->name;
$contents = $tag->contents;
$attr_count = count($tag->attributes);
$child_count = count($tag->tags);
$empty_tag = ($tag->contents == '') ? true : false;
// Create intial tag
if ($attr_count == 0) {
// No attributes
if ($empty_tag === true) {
$final = "<$name />";
} else {
$final = "<$name>$contents$name>";
}
} else {
// Attributes present
$attribs = '';
foreach ($tag->attributes as $key => $value) {
$attribs .= ' ' . $key . "=\"$value\"";
}
if ($empty_tag === true) {
$final = "<$name$attribs />\n";
} else {
$final = "<$name$attribs>$contents$name>\n";
}
}
// Search for children
if ($child_count > 0) {
foreach ($tag->tags as $childID) {
$final = $this->createXML($childID,$final);
}
}
if ($parentXML != '') {
// Add tag XML to parent XML
$stop1 = strrpos($parentXML,'');
$stop2 = strrpos($parentXML,' />');
if ($stop1 > $stop2) {
// Parent already has children
$begin_chunk = substr($parentXML,0,$stop1);
$end_chunk = substr($parentXML,$stop1,(strlen($parentXML) - $stop1 + 1));
$final = $begin_chunk . $final . $end_chunk;
} elseif ($stop2 > $stop1) {
// No previous children
$spc = strpos($parentXML,' ',0);
$parent_name = substr($parentXML,1,$spc - 1);
if ($spc != $stop2) {
// Attributes present
$parent_attribs = substr($parentXML,$spc,($stop2 - $spc));
} else {
// No attributes
$parent_attribs = '';
}
$final = "<$parent_name$parent_attribs>$final$parent_name>";
}
}
return $final;
}
function getTag($tagID,&$name,&$attributes,&$contents,&$tags) {
// Returns tag information via variable references from a tag index#
// Get object reference for tag
$tag =& $this->xml_index[$tagID];
$name = $tag->name;
$attributes = $tag->attributes;
$contents = $tag->contents;
$tags = $tag->tags;
}
function &getTagByID($tagID) {
// Returns tag information via variable references from a tag index#
// Get object reference for tag
$tag =& $this->xml_index[$tagID];
return $tag;
}
function getChildByName($parentID,$childName,$startIndex=0) {
// Returns child index# searching by name
// Get reference for parent
$parent =& $this->xml_index[$parentID];
if ($startIndex > count($parent->tags)) return false;
for ($i = $startIndex; $i < count($parent->tags); $i++) {
$childID = $parent->tags[$i];
// Get reference for child
$child =& $this->xml_index[$childID];
if ($child->name == $childName) {
// Found child, return index#
return $childID;
}
}
}
}
class xml_tag {
var $refID; // Unique ID number of the tag
var $name; // Name of the tag
var $attributes = array(); // Array (assoc) of attributes for this tag
var $tags = array(); // An array of refID's for children tags
var $contents; // textual (CDATA) contents of a tag
var $children = array(); // Collection (type: xml_tag) of child tag's
function xml_tag(&$document,$tag_name,$tag_attrs=array(),$tag_contents='') {
// Constructor function for xml_tag class
// Set object variables
$this->name = $tag_name;
$this->attributes = $tag_attrs;
$this->contents = $tag_contents;
$this->tags = array(); // Initialize children array/collection
$this->children = array();
}
function addChild (&$document,$tag_name,$tag_attrs=array(),$tag_contents='') {
// Adds a child tag object to the current tag object
// Create child instance
$this->children[(count($this->children))] = new xml_tag($document,$tag_name,$tag_attrs,$tag_contents);
// Add object reference to document index
$document->xml_index[$document->xml_reference] =& $this->children[(count($this->children) - 1)];
// Assign document index# to child
$document->xml_index[$document->xml_reference]->refID = $document->xml_reference;
// Add child index# to parent collection of child indices
array_push($this->tags,$document->xml_reference);
// Update document index counter
$document->xml_reference++;
// Return child index#
return ($document->xml_reference - 1);
}
}
?>