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 .= "\nroot_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\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"; 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) . ""; } /*-------------------------------------------------------------------------*/ // 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; } } ?>