As we are now progressing towards XML generation, what to do with it? I altered a little code from the PHP page about the XML parser to arrange the XML in a treelike structure. Don't know where to put it, so I'll just dump it below ;-)
<?
# Three global functions, sorry guys function wgXMLstartElement($parser, $name, $attrs) { global $wgXMLobject;
// If var already defined, make array eval('$test=isset('.$wgXMLobject->tree.'->'.$name.');'); if ($test) { eval('$tmp='.$wgXMLobject->tree.'->'.$name.';'); eval('$arr=is_array('.$wgXMLobject->tree.'->'.$name.');'); if (!$arr) { eval('unset('.$wgXMLobject->tree.'->'.$name.');'); eval($wgXMLobject->tree.'->'.$name.'[0]=$tmp;'); $cnt = 1; } else { eval('$cnt=count('.$wgXMLobject->tree.'->'.$name.');'); }
$wgXMLobject->tree .= '->'.$name."[$cnt]"; } else { $wgXMLobject->tree .= '->'.$name; } if (count($attrs)) { eval($wgXMLobject->tree.'->attr=$attrs;'); } }
function wgXMLendElement($parser, $name) { global $wgXMLobject; // Strip off last -> for($a=strlen($wgXMLobject->tree);$a>0;$a--) { if (substr($wgXMLobject->tree, $a, 2) == '->') { $wgXMLobject->tree = substr($wgXMLobject->tree, 0, $a); break; } } }
function wgXMLcharacterData($parser, $data) { global $wgXMLobject;
eval($wgXMLobject->tree.'->data=''.$data.'';'); }
# Here's the class that generates a nice tree class wikiXML { function init_object () { global $wgXMLobject ; $wgXMLobject->tree = '$wgXMLobject->xml'; $wgXMLobject->xml = ''; }
function scanFile ( $filename ) { $this->init_object () ; $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "wgXMLstartElement", "wgXMLendElement"); xml_set_character_data_handler($xml_parser, "wgXMLcharacterData"); if (!($fp = fopen($filename, "r"))) { die("could not open XML input"); }
while ($data = fread($fp, 4096)) { if (!xml_parse($xml_parser, $data, feof($fp))) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } } xml_parser_free($xml_parser); }
function scanString ( &$data ) { $this->init_object () ; $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "wgXMLstartElement", "wgXMLendElement"); xml_set_character_data_handler($xml_parser, "wgXMLcharacterData"); if (!xml_parse($xml_parser, $data, true)) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } xml_parser_free($xml_parser); }
function is_list ( &$xml ) {
}
function parseit ( &$xml ) { print_r ( $xml ) ; }
}
$w = new wikiXML ; $filename = 'sample.xml'; $w->scanFile ( $filename ) ; $w->parseit ( $wgXMLobject->xml ) ; return 0;
?>
Magnus Manske wrote:
As we are now progressing towards XML generation, what to do with it? I altered a little code from the PHP page about the XML parser to arrange the XML in a treelike structure. Don't know where to put it, so I'll just dump it below ;-)
Using the eval function makes it a bit hard to understand and I suspect it isn't very efficient. How about the following:
<?
// the base class for an element class element { var $name = ""; var $attrs = array(); var $children = array();
function myPrint() { echo "<UL>"; echo "<LI> <B> Name: </B> $this->name"; // print attributes echo "<LI> <B> Attributes: </B>"; foreach ($this->attrs as $name => $value) { echo "$name => $value; " ; } // print children foreach ($this->children as $child) { if ( is_string($child) ) { echo "<LI> $child"; } else { $child->myPrint(); } } echo "</UL>"; }
}
$ancStack = array(); // the stack with ancestral elements $allElem = array(); // the stack with all elements in the tree
// Three global functions needed for parsing, sorry guys function wgXMLstartElement($parser, $name, $attrs) { global $ancStack, $allElem;
$newElem = new element; $newElem->name = $name; $newElem->attrs = $attrs; array_push($allElem, $newElem); $newIndex = count($allElem)-1; // add to parent if parent exists if ( $ancStack ) { array_push($ancStack[count($ancStack)-1]->children, &$allElem[$newIndex]); } // push new element itself on ancestor stack array_push($ancStack, &$allElem[$newIndex]); }
function wgXMLendElement($parser, $name) { global $ancStack;
// pop element of stack array_pop($ancStack); }
function wgXMLcharacterData($parser, $data) { global $ancStack; // add to parent if parent exists if ( $ancStack ) { array_push($ancStack[count($ancStack)-1]->children, $data); } }
# Here's the class that generates a nice tree class xml2php {
function &scanFile( $filename ) { global $allElem;
$xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "wgXMLstartElement", "wgXMLendElement"); xml_set_character_data_handler($xml_parser, "wgXMLcharacterData"); if (!($fp = fopen($filename, "r"))) { die("could not open XML input"); } while ($data = fread($fp, 4096)) { if (!xml_parse($xml_parser, $data, feof($fp))) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } } xml_parser_free($xml_parser);
return $allElem[0]; }
}
$w = new xml2php; $filename = 'sample.xml'; $result = $w->scanFile( $filename ); $result->myPrint();
return 0;
?>
On Tuesday 17 August 2004 21:38, Jan Hidders wrote:
Magnus Manske wrote:
As we are now progressing towards XML generation, what to do with it? I altered a little code from the PHP page about the XML parser to arrange the XML in a treelike structure. Don't know where to put it, so I'll just dump it below ;-)
Using the eval function makes it a bit hard to understand and I suspect it isn't very efficient. How about the following: [...]
Here is a better version that doesn't require an array that stores all elements in the tree:
<?
// the base class for an element class element { var $name = ""; var $attrs = array(); var $children = array();
function myPrint() { echo "<UL>"; echo "<LI> <B> Name: </B> $this->name"; // print attributes echo "<LI> <B> Attributes: </B>"; foreach ($this->attrs as $name => $value) { echo "$name => $value; " ; } // print children foreach ($this->children as $child) { if ( is_string($child) ) { echo "<LI> $child"; } else { $child->myPrint(); } } echo "</UL>"; }
}
$ancStack = array(); // the stack with ancestral elements
// Three global functions needed for parsing, sorry guys function wgXMLstartElement($parser, $name, $attrs) { global $ancStack, $rootElem;
$newElem = new element; $newElem->name = $name; $newElem->attrs = $attrs; array_push($ancStack, $newElem); // add to parent if parent exists $nrAncs = count($ancStack)-1; if ( $nrAncs > 0 ) { array_push($ancStack[$nrAncs-1]->children, &$ancStack[$nrAncs]); } else { // make extra copy of root element and alias it with the original array_push($ancStack, &$ancStack[0]); } }
function wgXMLendElement($parser, $name) { global $ancStack, $rootElem;
// pop element of stack array_pop($ancStack); }
function wgXMLcharacterData($parser, $data) { global $ancStack, $rootElem;
// add to parent if parent exists if ( $ancStack ) { array_push($ancStack[count($ancStack)-1]->children, $data); } }
# Here's the class that generates a nice tree class xml2php {
function &scanFile( $filename ) { global $ancStack;
$xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "wgXMLstartElement", "wgXMLendElement"); xml_set_character_data_handler($xml_parser, "wgXMLcharacterData"); if (!($fp = fopen($filename, "r"))) { die("could not open XML input"); } while ($data = fread($fp, 4096)) { if (!xml_parse($xml_parser, $data, feof($fp))) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } } xml_parser_free($xml_parser);
// return the remaining root element we copied in the beginning return $ancStack[0]; }
}
$w = new xml2php; $filename = 'sample.xml'; $result = $w->scanFile( $filename ); $result->myPrint();
return 0;
?>
I have checked in a silghtly modified version of this as ParserXML.php into CVS HEAD.
Magnus
Jan Hidders wrote:
On Tuesday 17 August 2004 21:38, Jan Hidders wrote:
Magnus Manske wrote:
As we are now progressing towards XML generation, what to do with it? I altered a little code from the PHP page about the XML parser to arrange the XML in a treelike structure. Don't know where to put it, so I'll just dump it below ;-)
Using the eval function makes it a bit hard to understand and I suspect it isn't very efficient. How about the following: [...]
Here is a better version that doesn't require an array that stores all elements in the tree:
<? // the base class for an element class element { var $name = ""; var $attrs = array(); var $children = array(); function myPrint() { echo "<UL>"; echo "<LI> <B> Name: </B> $this->name"; // print attributes echo "<LI> <B> Attributes: </B>"; foreach ($this->attrs as $name => $value) { echo "$name => $value; " ; } // print children foreach ($this->children as $child) { if ( is_string($child) ) { echo "<LI> $child"; } else { $child->myPrint(); } } echo "</UL>"; } } $ancStack = array(); // the stack with ancestral elements // Three global functions needed for parsing, sorry guys function wgXMLstartElement($parser, $name, $attrs) { global $ancStack, $rootElem; $newElem = new element; $newElem->name = $name; $newElem->attrs = $attrs; array_push($ancStack, $newElem); // add to parent if parent exists $nrAncs = count($ancStack)-1; if ( $nrAncs > 0 ) { array_push($ancStack[$nrAncs-1]->children, &$ancStack[$nrAncs]); } else { // make extra copy of root element and alias it with the original array_push($ancStack, &$ancStack[0]); } } function wgXMLendElement($parser, $name) { global $ancStack, $rootElem; // pop element of stack array_pop($ancStack); } function wgXMLcharacterData($parser, $data) { global $ancStack, $rootElem; // add to parent if parent exists if ( $ancStack ) { array_push($ancStack[count($ancStack)-1]->children, $data); } } # Here's the class that generates a nice tree class xml2php { function &scanFile( $filename ) { global $ancStack; $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "wgXMLstartElement", "wgXMLendElement"); xml_set_character_data_handler($xml_parser, "wgXMLcharacterData"); if (!($fp = fopen($filename, "r"))) { die("could not open XML input"); } while ($data = fread($fp, 4096)) { if (!xml_parse($xml_parser, $data, feof($fp))) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } } xml_parser_free($xml_parser); // return the remaining root element we copied in the beginning return $ancStack[0]; } } $w = new xml2php; $filename = 'sample.xml'; $result = $w->scanFile( $filename ); $result->myPrint(); return 0; ?>
Wikitech-l mailing list Wikitech-l@wikimedia.org http://mail.wikipedia.org/mailman/listinfo/wikitech-l
Magnus Manske wrote:
// If var already defined, make array eval('$test=isset('.$wgXMLobject->tree.'->'.$name.');');
In case you didn't know, you _can_ write code like this:
$test = isset( ${$wgXMLobject->tree}->$name );
While it's amazingly ugly and probably a bad idea anyway;) it's going to be more efficient than the even uglier use of an eval() that has to parse and compile entire PHP statements at runtime. (For the above case, about three times faster.)
-- brion vibber (brion @ pobox.com)
wikitech-l@lists.wikimedia.org