xml分析类与xml创建函数

作者:袖梨 2022-07-02

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 .="";
  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文档


include_once('swiftxml.1.1.php教程');

$XML= swiftXML_use_file('http://www.111cn.net教程/feed/rss2/');


echo "

".$XML->get("/channel/title")."

";
echo "

".$XML->get("/channel/description")."

";

foreach ($XML->get("//item") as $item)
{ $url   = $item->get("link");
 $title = $item->get("title");
 $desc  = $item->get("description");

 echo html_entity_decode("

$title

$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();

?>

相关文章

精彩推荐