class arrayTree
{
private $stack;
private $tree;
private $location;
private $locationstring;
public function __construct($tree = false)
{ $this->stack = array();
if ($tree)
$this->tree = $tree;
else
$this->tree = array();
$this->location = 0;
}
public function startBranch()
{ $this->location++;
$this->stack[] = $this->location;
$this->location = 0;
$this->nodes = 0;
$this->locationstring = "";
foreach($this->stack as $v)
$this->locationstring .="['node:$v']";
eval('$this->tree'."$this->locationstring = array(); ");
eval('$this->tree'."$this->locationstring"."['nodes'] = 0; ");
}
public function addLeaf($name, $value)
{ $name = htmlspecialchars($name, ENT_QUOTES);
if (is_array($value) && sizeof($value)> 0)
{ $arr = "array( ";
foreach($value as $n=>$v)
{ $v = addslashes("$v");
$arr .= "'$n' => '$v',";
}
$arr .= "'$n' => '$v')";
//echo '$this->tree'."$this->locationstring"."['$name']"." = $arr; ";
eval ('$this->tree'."$this->locationstring"."['$name']"." = $arr; ");
}
else
{
if (is_array($value) && sizeof($value)== 0)
$value = '';
$value = htmlspecialchars($value, ENT_QUOTES);
$tmp = '$this->tree'."$this->locationstring"."['$name']".' = "$value";'." ";
//echo ($tmp);
eval($tmp);
}
}
public function endBranch()
{
$this->location = array_pop($this->stack);
$this->locationstring = "";
foreach($this->stack as $v)
$this->locationstring .= "['node:$v']";
eval('$this->tree'."$this->locationstring"."['nodes'] = $this->location; ");
}
public function gettree()
{ return $this->tree;
}
}
/***************************************************
** XMLParser Object
** Helper object for parsing XML into an arrayTree
***************************************************/
class XMLParser
{
private $filename;
private $data;
private $currentItem;
private $didread;
private $depth;
private $deptharr;
private $parsed;
private $pointer;
private $parser;
private $p;
private $arrayout;
private $tree;
public function __construct($xml, $isfile = true)
{
if ($isfile)
{ $file = $xml;
$this->filename = $file;
}
else
{ $this->data = $xml;
$this->filename = false;
}
$this->tree = new arrayTree;
$this->tree->addLeaf('nodes', 0);
$this->depth = 0;
$this->deptharr = array();
$this->pointer = '$this->parsed';
$this->currentItem = array();
$this->didread = false;
$this->parsed = array();
$this->arrayout = "";
}
public function startElement($parser, $name, $attrs)
{ $this->parsed = "";
$this->tree->startBranch();
$this->tree->addLeaf('name', $name);
$this->tree->addLeaf('attributes', $attrs);
}
public function characterData($parser, $data)
{ if (!$this->didread)
$this->parsed = $data;
else
$this->parsed .= $data;
$this->didread = true;
}
public function endElement($parser, $name)
{ $this->tree->addLeaf('value',$this->parsed);
$this->parsed = "";
$this->tree->endBranch();
}
public function parse()
{
$this->parser = xml_parser_create();
xml_set_object($this->parser, $this);
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler($this->parser, "startElement", "endElement");
xml_set_character_data_handler($this->parser, "characterData");
if ($this->filename !== false)
{ $data = file_get_contents($this->filename);
if (!$data)
return false;
}
else
$data = $this->data;
$data=eregi_replace(">"."[[:space:]]+"."<","><",$data);
$data=str_replace("&","&",$data);
if (!xml_parse($this->parser, $data))
{ die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->parser)),
xml_get_current_line_number($this->parser)));
}
xml_parser_free($this->parser);
$data=str_replace("&","&",$this->tree->gettree());
return $data['node:1'];
}
}
/***************************************************
** swiftXML Object
** Allows user access to XML data stored in tree
***************************************************/
class swiftXML implements IteratorAggregate
{
private $XMLtree;
public function __construct(&$xml = false, $type = XML_FILE)
{
if (is_array($xml) || $type == XML_TREE)
{ $this->usearray($xml);
}
else if ($type == XML_FILE)
{ $this->usefile($xml);
}
else if ($type == XML_TEXT)
{ $this->usetext($xml);
}
}
public function & __get($x)
{
return $this->get($x);
}
public function __set($x,$y)
{
$this->set($x,$y);
}
public function __call($x, $y)
{ if (array_key_exists($x,$this->XMLtree))
return $this->XMLtree[$x];
else
return false;
}
public function __toString()
{
return $this->XMLtree['value'];
}
// Iterator function
public function getIterator()
{ return new ArrayIterator($this->XMLtree);
}
// initialize functions
public function usefile($file)
{ $x = new XMLParser($file);
$this->XMLtree = $x->parse();
}
public function usetext($text)
{ $x = new XMLParser($text,false);
$this->XMLtree = $x->parse();
}
public function usearray(&$arr)
{ $this->XMLtree = $arr;
}
// return Tree as XML
public function asXML($header = true, $tree = false, $depth = 0)
{ if (!$tree)
$tree = $this->XMLtree;
$output = "";
if ($header)
{
$output = " ";
}
$tabs = str_repeat (" ",$depth);
$output .= "$tabs<$tree[name]";
if ($tree['attributes'] != "" && is_array($tree['attributes']))
{ foreach ($tree['attributes'] as $n => $v)
$output .= " $n="$v"";
}
$output .= ">$tree[value]";
if ($tree['nodes'] > 0)
{ foreach ($tree as $n => $v)
{ if (substr($n,0,5) == "node:")
$output .= " " . $this->asXML(false,$tree[$n],$depth+1);
}
$output .=" $tabs";
}
$output .="$tree[name]>";
return $output;
}
// return XMLtree
public function getDetailedTree()
{ return $this->XMLtree;
}
// return a simplified tree as an array, where the array keys correspond to XML tags
public function getSimpleTree($showattribs = false, &$tree = false)
{ if (!$tree)
$tree = $this->XMLtree;
// tree has no branches
if (sizeof($tree) < 5)
return $tree['value'];
$output = array();
foreach($tree as $n=>$v)
{ if(substr($n,0,5) == 'node:')
{ $vname = $v['name'];
$attribstr = "";
$vattrib = $v['attributes'];
if (array_key_exists($vname, $output))
{ if (!is_array($output[$vname]) || !array_key_exists(0,$output[$vname]))
{ $existingvalue = $output[$vname];
$existingvattrib = false;
if ($showattribs && array_key_exists($vname."/attributes",$output))
$existingvattrib = $output[$vname."/attributes"];
$output = array();
$output[$vname] = array();
$output[$vname][] = $existingvalue;
if ($showattribs && $existingvattrib)
$output[$vname]["0/attributes"] = $existingvattrib;
}
$output[$vname][] = $this->getSimpleTree($showattribs,$v);
if ($showattribs && is_array($vattrib))
$output[$vname][end(array_keys($output[$vname]))."/attributes"] = $vattrib;
}
else
{
$output[$vname] = $this->getSimpleTree($showattribs, $v);
//echo "-->$vname:".$output[$vname]." ";
if ($showattribs && is_array($vattrib))
$output[$vname."/attributes"]= $vattrib;
}
}
}
return $output;
}
// $location takes the format "block1/block2/block3"
private function & getNodeByLocation($location, &$tree= false)
{ if (!$tree)
$tree = &$this->XMLtree;
$location = ereg_replace("^/", "",$location);
$location = ereg_replace("/$", "",$location);
if ($slashpos = strpos($location,"/"))
{ $nodename = substr($location,0,$slashpos);
$rest = substr($location,$slashpos+1,strlen($location)-$slashpos+1);
return $this->getNodeByLocation($rest,$this->getNodebyName($tree, $nodename));
}
else
return $this->getNodeByName($tree, $location);
}
public function doesExist($location)
{ return getNodeByLocation($location) ==! false ? true : false;
}
// returns XML object
public function & getNode($location)
{ $tmp = $this->getNodeByLocation($location);
if ($tmp === false)
return false;
else
return new swiftXML($tmp,XML_TREE);
}
// accepts $newnode as XML object
public function setNode($newnode, $location)
{ $locnode = &$this->getNodeByLocation($location);
//print_r($locnode);
$locnode = $newnode->getDetailedTree();
}
public function getValue($location)
{
$arr = $this->getNodeByLocation($location);
if ($arr !== false)
return $arr['value'];
else
return false;
}
public function setValue($value, $location = false)
{
if (!$location)
$arr = &$this->XMLtree;
else
$arr = &$this->getNodeByLocation($location);
$arr['value'] = $value;
}
public function set($location,$value)
{
if (is_array($value))
$this->setTree($value,$location);
else if (is_a($value, "swiftXML"))
$this->setNode($value,$location);
else
$this->setValue($value,$location);
}
public function setTree($value, $location= false)
{ if (!$location)
$arr = &$this->XMLtree;
else
$arr = &$this->getNodeByLocation($location);
$arr = $value;
}
public function getAttributes($location)
{
$arr = $this->getNodeByLocation($location);
return $arr['attributes'];
}
public function getAttribute($location, $attrib)
{
$arr = $this->getNodeByLocation($location);
if (array_key_exists($attrib, $arr['attributes']))
return $arr['attributes'][$attrib];
else
return false;
}
public function setAttribute($attribname, $attribvalue, $location = false)
{ if (!$location)
$arr = &$this->XMLtree;
else
$arr = &$this->getNodeByLocation($location);
if (!is_array($arr['attributes']))
$arr['attributes'] = array();
$arr['attributes'][$attribname] = $attribvalue;
}
public function setAttributes($arr, $location = false)
{ if (!$location)
$arr2 = &$this->XMLtree;
else
$arr2 = &$this->getNodeByLocation($location);
$arr2['attributes'] = $arr;
}
// Easiest way to get info from an XML document is to use function get()
// get() guesses what format you'd like the data in based on the data.
// It will return an array of XML objects if $location is ambiguous.
// If one tag exists at $location, it will be returned and an XML object, unless it has no attributes,
// in which case the value be returned as a string.
//
// Use the prefix // to indicate a location wildcard (run getNodeArrayRecursize)
public function get($location)
{
if (ereg("^//",$location) || ereg("^*/",$location))
return $this->getNodeArrayRecursive(substr($location,2,strlen($location)-2));
$output = $this->getNodeArray($location);
if ($output !== false && count($output) == 1)
{ $tree = $output[0]->getDetailedTree();
if ($tree['nodes'] == 0 && !is_array($tree['attributes']))
$output = $tree['value'];
else
$output = $output[0];
}
return $output;
}
public function getNodeArray($location)
{
if (ereg("^//",$location) || ereg("^*/",$location))
return $this->getNodeArrayRecursive(substr($location,2,strlen($location)-2));
$output = array();
$lastpos = strrpos($location, "/");
if ($lastpos !== false)
{ $subloc = substr($location,0,$lastpos);
$nodename = substr($location,$lastpos+1,strlen($location)-1);
$node = $this->getNode($subloc);
if ($node === false)
return false;
$tree = $node->getDetailedTree();
}
else
{ $subloc = $location;
$nodename = $location;
$tree = $this->XMLtree;
}
for ($i = 1; $i <= $tree['nodes']; $i++)
{ if ($tree["node:$i"]['name'] == $nodename)
$output[] = swiftXML_use_tree($tree["node:$i"]);
}
if (count($output) == 0)
return false;
else
return $output;
}
// returns an array of any node named $location in $tree
private function getNodeArrayRecursive($location, $tree = false)
{ if (!$tree)
$tree = $this->XMLtree;
$output = array();
if ($tree['name'] == $location)
$output[] = swiftXML_use_tree($tree);
for ($i = 1; $i <= $tree['nodes']; $i++)
$output =array_merge($output, $this->getNodeArrayRecursive($location,$tree["node:$i"]));
return $output;
}
// assistant function; pulls a Subarray from the $tree
private function & getNodeByName(&$tree, $name, $debug = false)
{ if ($debug) echo "getNodeByName($tree,$name); ";
if (!is_array($tree))
{ if ($debug) echo ("[".$tree."]");
return false;
}
foreach ($tree as $n => $v)
{ if (is_array($v) and array_key_exists('name',$v))
{ if ($debug) echo $tree[$n]['name'] ." == $name ? ";
if ($v['name'] == $name)
return $tree[$n];
}
if ($debug) echo $n." ";
}
return false;
}
public function createChild($name, $value = "", $attributes = "")
{
$nodes = ++$this->XMLtree['nodes'];
if (is_a($name, "swiftXML"))
{ $this->XMLtree["node:$nodes"] = $name->getDetailedTree();
$nodes = $this->XMLtree['nodes'];
}
else
$this->XMLtree["node:$nodes"] = array( "name" => $name,
"value" => $value,
"attributes" => $attributes,
"nodes" => 0);
return $nodes;
}
}
define("XML_FILE","file");
define("XML_TREE","tree");
define("XML_TEXT","text");
define("XML_NO_CURL",false);
// assistant functions for initializing XML objects
function & swiftXML_use_file($filename, $use_curl = true)
{
if (ereg("://",$filename) && $use_curl && function_exists('curl_init'))
return swiftXML_use_curl($filename);
else
return new swiftXML($filename, XML_FILE);
}
function & swiftXML_use_text($text)
{ return new swiftXML($text, XML_TEXT);
}
function & swiftXML_use_tree($tree)
{ return new swiftXML($tree, XML_TREE);
}
function & swiftXML_use_curl($filename)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $filename);
curl_setopt($ch, CURLOPT_USERAGENT, "swiftXML/1.1");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
$text = curl_exec($ch);
curl_close($ch);
return new swiftXML($text, XML_TEXT);
}
function & swiftXML_create($name, $value = "", $attributes = "")
{
return swiftXML_use_tree(array( "name" => $name,
"value" => $value,
"attributes" => $attributes,
"nodes" => 0));
}
?>
分析xml文档
$XML= swiftXML_use_file('http://www.111cn.net教程/feed/rss2/');
echo "
foreach ($XML->get("//item") as $item)
{ $url = $item->get("link");
$title = $item->get("title");
$desc = $item->get("description");
echo html_entity_decode("
$desc
");}
?>
下创建 xml 文档
include_once('swiftxml.1.1.php');
$rss = swiftXML_create("rss");
$rss->setAttribute("version", "2.0");
$channel = swiftXML_create("channel");
$channel->createChild("title","Swiftly Tilting");
$channel->createChild("link","http://www.111com.net");
for($i = 0; $i < 10; $i++)
{ $item = swiftXML_create("item");
$item->createChild("title","title $i");
$item->createChild("description","description $i");
$channel->createChild($item);
}
$rss->createChild($channel);
header("Content-type: text/xml");
echo $rss->asXML();
?>