XML handling methods (KERNEL)
| > Module written by Matt Mecham
| > Date started: 25th February
|
| > Module Version Number: 1.0.0
+--------------------------------------------------------------------------
This is a descrption
Baked Beans
103
# Set the root tag
$xml->xml_set_root( 'productlist', array( 'name' => 'myname', 'version' => '1.0' ) );
# Add a group
$xml->xml_add_group( 'productgroup', array( 'name' => 'thisgroup' ) );
# Build entry content
$content[] = $xml->xml_build_simple_tag( 'description', "This is a descrption" );
$content[] = $xml->xml_build_simple_tag( 'title' , "Baked Beans" );
$content[] = $xml->xml_build_simple_tag( 'room' , '103' , array( 'store' => 1 ) );
# Build entry
$entry[] = $xml->xml_build_entry( 'product', $content, array( 'id' => '1.0' ) );
# Add to group 'productlist'
$xml->xml_add_entry_to_group( 'productgroup', $entry );
# Format..
$xml->xml_format_document();
# Get XML document
$filecontents = $xml->xml_document;
# Parse XML document
$xml->xml_parse_document( $filecontents );
# Show XML array
print_r( $xml->xml_array );
# print "Baked Beans";
print $xml->xml_array['productlist']['productgroup']['product'][0]['title']['VALUE'];
# print "1";
print $xml->xml_array['productlist']['productgroup']['product'][0]['room']['ATTRIBUTES']['store'];
*/
class class_xml
{
var $header = '';
var $root_tag = '';
var $root_attributes = "";
var $entries = array();
var $xml_document = "";
var $depth = 0;
var $tmp_doc = "";
var $groups = "";
var $index_numeric = 0;
var $collapse_dups = 1;
var $xml_array = array();
var $collapse_newlines = 1;
/*-------------------------------------------------------------------------*/
// CONSTRUCTOR
/*-------------------------------------------------------------------------*/
function class_xml()
{
}
/*-------------------------------------------------------------------------*/
// Parse an XML document into arrays
/*-------------------------------------------------------------------------*/
function xml_parse_document( $xml )
{
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE , 0);
xml_parse_into_struct($parser, $xml, $vals, $index);
xml_parser_free($parser);
$i = -1;
$this->xml_array = $this->_xml_get_children($vals, $i);
}
/*-------------------------------------------------------------------------*/
// Format the XML document
/*-------------------------------------------------------------------------*/
function xml_format_document( $entry=array() )
{
$this->xml_document = $this->header ? $this->header."\n" : '';
$this->xml_document .= "<".$this->root_tag.$this->root_attributes.">\n";
$this->xml_document .= $this->tmp_doc;
$this->xml_document .= "\n".$this->root_tag.">";
$this->tmp_doc = "";
}
/*-------------------------------------------------------------------------*/
// Set the root tags
/*-------------------------------------------------------------------------*/
function xml_set_root($tag, $attributes=array() )
{
$this->root_tag = $tag;
$this->root_attributes = $this->_xml_build_attribute_string( $attributes );
}
/*-------------------------------------------------------------------------*/
// Add entries to the group
/*-------------------------------------------------------------------------*/
function xml_add_entry_to_group($tag, $entry=array() )
{
$this->tmp_doc .= "\t".$this->groups[ $tag ];
if ( is_array( $entry ) and count( $entry ) )
{
foreach( $entry as $e )
{
$this->tmp_doc .= "\n\t\t".$e."\n";
}
}
$this->tmp_doc .= "\t".$tag.">\n";
}
/*-------------------------------------------------------------------------*/
// Builds an entry
/*-------------------------------------------------------------------------*/
function xml_build_entry( $tag, $content=array(), $attributes=array() )
{
$entry = "<" . $tag . $this->_xml_build_attribute_string($attributes) . ">\n";
if ( is_array( $content ) and count( $content ) )
{
foreach( $content as $c )
{
$entry .= "\t\t\t".$c."\n";
}
}
$entry .= "\t\t" . $tag . ">";
return $entry;
}
/*-------------------------------------------------------------------------*/
// Add a group
/*-------------------------------------------------------------------------*/
function xml_add_group( $tag, $attributes=array() )
{
$this->groups[ $tag ] = "<" . $tag . $this->_xml_build_attribute_string($attributes) . ">";
}
/*-------------------------------------------------------------------------*/
// Builds a simple content structure
/*-------------------------------------------------------------------------*/
function xml_build_simple_tag( $tag, $description="", $attributes=array() )
{
return "<" . $tag . $this->_xml_build_attribute_string($attributes) . ">" . $this->_xml_encode_string($description) . "" . $tag . ">";
}
/*-------------------------------------------------------------------------*/
// INTERNAL: Build tree node
// Based on code found at http://php.net/manual/en/function.xml-parse-into-struct.php
// And http://eric.pollmann.net/work/public_domain/
/*-------------------------------------------------------------------------*/
function _xml_build_tag( $thisvals, $vals, &$i, $type )
{
$tag = array();
if ( isset($thisvals['attributes']) )
{
$tag['ATTRIBUTES'] = $this->_xml_decode_attribute($thisvals['attributes']);
}
if ( $type === 'complete' )
{
$tag['VALUE'] = $thisvals['value'];
}
else
{
$tag = array_merge( $tag, $this->_xml_get_children($vals, $i) );
}
return $tag;
}
/*-------------------------------------------------------------------------*/
// INTERNAL: Build a nested array of children
// Based on code found at http://php.net/manual/en/function.xml-parse-into-struct.php
// And http://eric.pollmann.net/work/public_domain/
/*-------------------------------------------------------------------------*/
function _xml_get_children($vals, &$i)
{
$children = array();
//-----------------------------------
// CDATA before children
//-----------------------------------
if ( $i > -1 && isset( $vals[$i]['value'] ) )
{
$children['VALUE'] = $vals[$i]['value'];
}
//-----------------------------------
// Loopy loo
//-----------------------------------
while( ++$i < count( $vals ) )
{
$type = $vals[$i]['type'];
//-----------------------------------
// CDATA after children
//-----------------------------------
if ($type === 'cdata')
{
$children['VALUE'] .= $vals[$i]['value'];
}
//-----------------------------------
// COMPLETE: At end of current branch
// OPEN: Node has children, recurse
//-----------------------------------
else if ( $type === 'complete' OR $type === 'open' )
{
$tag = $this->_xml_build_tag( $vals[$i], $vals, $i, $type );
if ( $this->index_numeric )
{
$tag['TAG'] = $vals[$i]['tag'];
$children[] = $tag;
}
else
{
$children[$vals[$i]['tag']][] = $tag;
}
}
//-----------------------------------
// End of node?
//-----------------------------------
else if ($type === 'close')
{
break;
}
}
if ( $this->collapse_dups )
{
foreach( $children as $key => $value )
{
if ( is_array($value) && (count($value) == 1) )
{
$children[$key] = $value[0];
}
}
}
return $children;
}
/*-------------------------------------------------------------------------*/
// INTERNAL: Builds attribute string
/*-------------------------------------------------------------------------*/
function _xml_build_attribute_string( $array = array() )
{
if ( is_array( $array ) and count( $array ) )
{
$string = array();
foreach( $array as $k => $v )
{
$v = trim( $this->_xml_encode_attribute($v) );
$string[] = $k.'="'.$v.'"';
}
return ' ' . implode( " ", $string );
}
}
/*-------------------------------------------------------------------------*/
// INTERNAL: Encodes an attribute string
/*-------------------------------------------------------------------------*/
function _xml_encode_attribute( $t )
{
$t = preg_replace("/&(?!#[0-9]+;)/s", '&', $t );
$t = str_replace( "<", "<" , $t );
$t = str_replace( ">", ">" , $t );
$t = str_replace( '"', """, $t );
$t = str_replace( "'", ''', $t );
return $t;
}
/*-------------------------------------------------------------------------*/
// INTERNAL: Encodes an attribute string
/*-------------------------------------------------------------------------*/
function _xml_decode_attribute( $t )
{
$t = str_replace( "&" , "&", $t );
$t = str_replace( "<" , "<", $t );
$t = str_replace( ">" , ">", $t );
$t = str_replace( """, '"', $t );
$t = str_replace( "'", "'", $t );
return $t;
}
/*-------------------------------------------------------------------------*/
// INTERNAL: Encodes a string to make it safe (uses cdata)
/*-------------------------------------------------------------------------*/
function _xml_encode_string( $v )
{
if ( preg_match( "/['\"\[\]<>&]/", $v ) )
{
$v = "_xml_convert_safecdata($v) . "]]>";
}
if ( $this->collapse_newlines )
{
$v = str_replace( "\r\n", "\n", $v );
}
return $v;
}
/*-------------------------------------------------------------------------*/
// INTERNAL: Ensures no embedding of cdata
/*-------------------------------------------------------------------------*/
function _xml_convert_safecdata( $v )
{
$v = str_replace( "" , "|¢]>" , $v );
return $v;
}
/*-------------------------------------------------------------------------*/
// INTERNAL: Uncoverts safe embedding
/*-------------------------------------------------------------------------*/
function _xml_unconvert_safecdata( $v )
{
$v = str_replace( "" , "]]>" , $v );
return $v;
}
}
?>