用 PHP5 輕松解析 XML
用 sax 方式的時(shí)候,要自己構(gòu)建3個(gè)函數(shù),而且要直接用這三的函數(shù)來(lái)返回?cái)?shù)據(jù),要求較強(qiáng)的邏輯。在處理不同結(jié)構(gòu)的 xml 的時(shí)候,還要重新進(jìn)行構(gòu)造這三個(gè)函數(shù),麻煩!
用 dom 方式,倒是好些,但是他把每個(gè)節(jié)點(diǎn)都看作是一個(gè) node,,操作起來(lái)要寫(xiě)好多的代碼,麻煩!
網(wǎng)上有好多的開(kāi)源的 xml 解析的類(lèi)庫(kù),以前看過(guò)幾個(gè),但是心里總是覺(jué)得不踏實(shí),感覺(jué)總是跟在別人的屁股后面。
這幾天在搞 Java,挺累的,所以決定換換腦袋,寫(xiě)點(diǎn) PHP 代碼,為了防止以后 XML 解析過(guò)程再令我犯難,就花了一天的時(shí)間寫(xiě)了下面一個(gè) XML 解析的類(lèi),于是就有了下面的東西。
實(shí)現(xiàn)方式是通過(guò)包裝“sax方式的解析結(jié)果”來(lái)實(shí)現(xiàn)的??偟膩?lái)說(shuō),對(duì)于我個(gè)人來(lái)說(shuō)挺實(shí)用的,性能也還可以,基本上可以完成大多數(shù)的處理要求。
功能:
1\ 對(duì)基本的 XML 文件的節(jié)點(diǎn)進(jìn)行 查詢 / 添加 / 修改 / 刪除 工作。
2\ 導(dǎo)出 XML 文件的所有數(shù)據(jù)到一個(gè)數(shù)組里面。
3\ 整個(gè)設(shè)計(jì)采用了 OO 方式,在操作結(jié)果集的時(shí)候,使用方法類(lèi)似于 dom
缺點(diǎn):
1\ 每個(gè)節(jié)點(diǎn)最好都帶有一個(gè)id(看后面的例子),每個(gè)“節(jié)點(diǎn)名字”=“節(jié)點(diǎn)的標(biāo)簽_節(jié)點(diǎn)的id”,如果這個(gè) id 值沒(méi)有設(shè)置,程序?qū)⒆詣?dòng)給他產(chǎn)生一個(gè) id,這個(gè) id 就是這個(gè)節(jié)點(diǎn)在他的上級(jí)節(jié)點(diǎn)中的位置編號(hào),從 0 開(kāi)始。
2\ 查詢某個(gè)節(jié)點(diǎn)的時(shí)候可以通過(guò)用“|”符號(hào)連接“節(jié)點(diǎn)名字”來(lái)進(jìn)行。這些“節(jié)點(diǎn)名字”都是按順序?qū)懞玫纳霞?jí)節(jié)點(diǎn)的名字。
使用說(shuō)明:
運(yùn)行下面的例子,在執(zhí)行結(jié)果頁(yè)面上可以看到函數(shù)的使用說(shuō)明
代碼是通過(guò) PHP5 來(lái)實(shí)現(xiàn)的,在 PHP4 中無(wú)法正常運(yùn)行。
由于剛剛寫(xiě)完,所以沒(méi)有整理文檔,下面的例子演示的只是一部分的功能,代碼不是很難,要是想知道更多的功能,可以研究研究源代碼。
目錄結(jié)構(gòu):
test.xml
xml / SimpleDocumentBase.php
xml / SimpleDocumentNode.php
xml / SimpleDocumentRoot.php
xml / SimpleDocumentParser.php
<?xml version="1.0" encoding="GB2312"?>
<shop>
<name>華聯(lián)</name>
<address>北京長(zhǎng)安街-9999號(hào)</address>
<desc>連鎖超市</desc>
<cat id="food">
<goods id="food11">
<name>food11</name>
<price>12.90</price>
</goods>
<goods id="food12">
<name>food12</name>
<price>22.10</price>
<desc creator="hahawen">好東西推薦</desc>
</goods>
</cat>
<cat>
<goods id="tel21">
<name>tel21</name>
<price>1290</price>
</goods>
</cat>
<cat id="coat">
<goods id="coat31">
<name>coat31</name>
<price>112</price>
</goods>
<goods id="coat32">
<name>coat32</name>
<price>45</price>
</goods>
</cat>
<special id="hot">
<goods>
<name>hot41</name>
<price>99</price>
</goods>
</special>
</shop>
文件:test.php
require_once "xml/SimpleDocumentParser.php";
require_once "xml/SimpleDocumentBase.php";
require_once "xml/SimpleDocumentRoot.php";
require_once "xml/SimpleDocumentNode.php";
$test->parse("test.xml");
$dom = $test->getSimpleDocument();
echo "下面是通過(guò)函數(shù)getSaveData()返回的整個(gè)xml數(shù)據(jù)的數(shù)組";
echo "</font><hr>";
print_r($dom->getSaveData());
echo "下面是通過(guò)setValue()函數(shù),給給根節(jié)點(diǎn)添加信息,添加后顯示出結(jié)果xml文件的內(nèi)容";
echo "</font><hr>";
$dom->setValue("telphone", "123456789");
echo htmlspecialchars($dom->getSaveXml());
echo "下面是通過(guò)getNode()函數(shù),返回某一個(gè)分類(lèi)下的所有商品的信息";
echo "</font><hr>";
$obj = $dom->getNode("cat_food");
$nodeList = $obj->getNode();
foreach($nodeList as $node){
$data = $node->getValue();
echo "<font color=red>商品名:".$data[name]."</font><br>";
print_R($data);
print_R($node->getAttribute());
}
echo "下面是通過(guò)findNodeByPath()函數(shù),返回某一商品的信息";
echo "</font><hr>";
$obj = $dom->findNodeByPath("cat_food|goods_food11");
if(!is_object($obj)){
echo "該商品不存在";
}else{
$data = $obj->getValue();
echo "<font color=red>商品名:".$data[name]."</font><br>";
print_R($data);
print_R($obj->getAttribute());
}
echo "下面是通過(guò)setValue()函數(shù),給商品\"food11\"添加屬性, 然后顯示添加后的結(jié)果";
echo "</font><hr>";
$obj = $dom->findNodeByPath("cat_food|goods_food11");
$obj->setValue("leaveword", array("value"=>"這個(gè)商品不錯(cuò)", "attrs"=>array("author"=>"hahawen", "date"=>date('Y-m-d'))));
echo htmlspecialchars($dom->getSaveXml());
echo "下面是通過(guò)removeValue()/removeAttribute()函數(shù),給商品\"food11\"改變和刪除屬性, 然后顯示操作后的結(jié)果";
echo "</font><hr>";
$obj = $dom->findNodeByPath("cat_food|goods_food12");
$obj->setValue("name", "new food12");
$obj->removeValue("desc");
echo htmlspecialchars($dom->getSaveXml());
echo "下面是通過(guò)createNode()函數(shù),添加商品, 然后顯示添加后的結(jié)果";
echo "</font><hr>";
$obj = $dom->findNodeByPath("cat_food");
$newObj = $obj->createNode("goods", array("id"=>"food13"));
$newObj->setValue("name", "food13");
$newObj->setValue("price", 100);
echo htmlspecialchars($dom->getSaveXml());
echo "下面是通過(guò)removeNode()函數(shù),刪除商品, 然后顯示刪除后的結(jié)果";
echo "</font><hr>";
$obj = $dom->findNodeByPath("cat_food");
$obj->removeNode("goods_food12");
echo htmlspecialchars($dom->getSaveXml());
?>
/**
*================================================
*
* @author hahawen(大齡青年)
* @copyright Copyright (c) 2004, NxCoder Group
*
*================================================
*/
/**
* class SimpleDocumentParser
* use SAX parse xml file, and build SimpleDocumentObject
* all this pachage's is work for xml file, and method is action as DOM.
*
* @package SmartWeb.common.xml
* @version 1.0
*/
class SimpleDocumentParser
{
private $currentName = null;
private $currentValue = null;
private $currentAttribute = null;
function getSimpleDocument()
{
return $this->domRootObject;
}
{
$xmlParser = xml_parser_create();
xml_parser_set_option($xmlParser,XML_OPTION_CASE_FOLDING,
0);
xml_parser_set_option($xmlParser,XML_OPTION_SKIP_WHITE, 1);
xml_parser_set_option($xmlParser,
XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_set_object($xmlParser, $this);
xml_set_character_data_handler($xmlParser,
"characterData");
xml_get_current_line_number($xmlParser)));
{
$this->currentName = $name;
$this->currentAttribute = $attrs;
if($this->currentNO == null)
{
$this->domRootObject = new SimpleDocumentRoot($name);
}
else
{
$this->currentNO = $this->currentNO->createNode($name, $attrs);
}
{
if($this->currentName==$name)
$tag = $this->currentNO->getSeq();
$this->currentNO = $this->currentNO->getPNodeObject();
if($this->currentAttribute!=null && sizeof($this->currentAttribute)>0)
$this->currentNO->setValue($name, array('value'=>$this->currentValue, 'attrs'=>$this->currentAttribute));
else
$this->currentNO->setValue($name, $this->currentValue);
}
else
{
$this->currentNO = (is_a($this->currentNO, 'SimpleDocumentRoot'))? null:
$this->currentNO->getPNodeObject();
}
}
{
$this->currentValue = iconv('UTF-8', 'GB2312', $data);
}
function __destruct()
{
unset($this->domRootObject);
}
?>
/**
*=================================================
*
* @author hahawen(大齡青年)
* @since 2004-12-04
* @copyright Copyright (c) 2004, NxCoder Group
*
*=================================================
*/
/**
* abstract class SimpleDocumentBase
* base class for xml file parse
* all this pachage's is work for xml file, and method is action as DOM.
*
* 1\ add/update/remove data of xml file.
* 2\ explode data to array.
* 3\ rebuild xml file
*
* @package SmartWeb.common.xml
* @abstract
* @version 1.0
*/
abstract class SimpleDocumentBase
{
private $values =
array();
{
$this->nodeTag = $nodeTag;
}
{
return $this->nodeTag;
}
$this->values = $values;
}
{
$this->values[$name] = $value;
}
{
return $name==null?
$this->values: $this->values[$name];
}
{
unset($this->values["$name"]);
}
$this->attributes = $attributes;
}
{
$this->attributes[$name] = $value;
}
{
return $name==null? $this->attributes:
$this->attributes[$name];
}
{
unset($this->attributes["$name"]);
}
{
return sizeof($this->nodes);
}
{
$this->nodes[$name]
= $nodeId;
}
{
return $name==null? $this->nodes: $this->nodes[$name];
}
{
$tmpObject = $rootNodeObj->createNodeObject($pId, $name, $attributes);
$key = isset($attributes[id])?
$name.'_'.$attributes[id]: $name.'_'.$this->getNodesSize();
$this->setNode($key, $tmpObject->getSeq());
return $tmpObject;
}
{
$rootNodeObj->removeNodeById($this->getNodeId($name));
if(sizeof($this->nodes)==1)
$this->nodes = array();
else
unset($this->nodes[$name]);
}
{
if($name==null)
{
$tmpList = array();
$tmpIds = $this->getNodeId();
foreach($tmpIds as $key=>$id)
$tmpList[$key] = $rootNodeObj->getNodeById($id);
return $tmpList;
}
else
{
$id = $this->getNodeId($name);
if($id===null)
{
$tmpIds = $this->getNodeId();
{
if(strpos($key, $name)==0)
{
$id = $tid;
break;
}
}
}
return $rootNodeObj->getNodeById($id);
}
}
{
$pos = strpos($path, '|');
if($pos<=0)
{
return $this->getNode($path);
}
else
{
$pos));
$tmpObj->findNodeByPath(substr($path,
$pos+1)):
null;
}
}
{
$data = $this->values;
if(sizeof($this->attributes)>0)
$nodeList = $this->getNode();
if($nodeList==null)
foreach($nodeList as $key=>$node)
{
$data[$key] = $node->getSaveData();
}
}
public function getSaveXml($level=0)
{
= str_pad("",
$level, "\t");
$str = "$prefixSpace<$this->nodeTag";
$str .= " $key=\"$value\"";
foreach($this->values as $key=>$value){
{
$str .= "$prefixSpace\t<$key";
}
else
$str .= "$prefixSpace\t<$key";
}
$tmpStr = trim(trim($tmpStr, "\r\n"));
$str .= $node->getSaveXml($level+1)."\r\n";
$str .= "$prefixSpace</$this->nodeTag>";
}
{
unset($this->nodes, $this->attributes, $this->values);
?>
/**
*==============================================
*
* @author hahawen(大齡青年)
* @since 2004-12-04
* @copyright Copyright (c) 2004, NxCoder Group
*
*==============================================
*/
/**
* class SimpleDocumentRoot
* xml root class, include values/attributes/subnodes.
* all this pachage's is work for xml file, and method is action as DOM.
*
* @package SmartWeb.common.xml
* @version 1.0
*/
{
private $prefixStr = '';
private $nodeLists = array();
{
parent::__construct($nodeTag);
}
{
$seq = sizeof($this->nodeLists);
$tmpObject = new SimpleDocumentNode($this,
$pNodeId, $name, $seq);
$tmpObject->setAttributes($attributes);
return $tmpObject;
}
{
if(sizeof($this->nodeLists)==1)
$this->nodeLists = array();
else
unset($this->nodeLists[$id]);
}
{
return $this->nodeLists[$id];
}
{
return $this->createNodeByName($this, $name, $attributes, -1);
}
{
return $this->removeNodeByName($this, $name);
}
{
return $this->getNodeByName($this, $name);
}
{
$prefixSpace = "";
$str = $this->prefixStr."\r\n";
return $str.parent::getSaveXml(0);
}
}
?>
/**
*===============================================
*
* @author hahawen(大齡青年)
* @since 2004-12-04
* @copyright Copyright (c) 2004, NxCoder Group
*
*===============================================
*/
/**
* class SimpleDocumentNode
* xml Node class, include values/attributes/subnodes.
* all this pachage's is work for xml file, and method is action as DOM.
*
* @package SmartWeb.common.xml
* @version 1.0
*/
class SimpleDocumentNode extends SimpleDocumentBase
{
private $seq = null;
private $rootObject = null;
private $pNodeId = null;
{
parent::__construct($nodeTag);
$this->rootObject = $rootObject;
$this->pNodeId = $pNodeId;
$this->seq = $seq;
}
{
return ($this->pNodeId==-1)?
$this->rootObject:
$this->rootObject->getNodeById($this->pNodeId);
}
return $this->seq;
}
{
return $this->createNodeByName($this->rootObject,
$name, $attributes,
$this->getSeq());
}
{
return $this->removeNodeByName($this->rootObject, $name);
}
public function getNode($name=null)
{
return $this->getNodeByName($this->rootObject,
$name);
}
}
?>
下面是通過(guò)函數(shù)getSaveData()返回的整個(gè)xml數(shù)據(jù)的數(shù)組
Array
(
[name] => 華聯(lián)
[address] => 北京長(zhǎng)安街-9999號(hào)
[desc] => 連鎖超市
[cat_food] => Array
(
[attrs] => Array
(
[id] => food
)
[goods_food11] => Array
(
[name] => food11
[price] => 12.90
[attrs] => Array
(
[id] => food11
)
)
[goods_food12] => Array
(
[name] => food12
[price] => 22.10
[desc] => Array
(
[value] => 好東西推薦
[attrs] => Array
(
[creator] => hahawen
)
)
[attrs] => Array
(
[id] => food12
)
)
)
[cat_1] => Array
(
[goods_tel21] => Array
(
[name] => tel21
[price] => 1290
[attrs] => Array
(
[id] => tel21
)
)
)
[cat_coat] => Array
(
[attrs] => Array
(
[id] => coat
)
[goods_coat31] => Array
(
[name] => coat31
[price] => 112
[attrs] => Array
(
[id] => coat31
)
)
[goods_coat32] => Array
(
[name] => coat32
[price] => 45
[attrs] => Array
(
[id] => coat32
)
)
)
[special_hot] => Array
(
[attrs] => Array
(
[id] => hot
)
[goods_0] => Array
(
[name] => hot41
[price] => 99
)
)
)
下面是通過(guò)setValue()函數(shù),給給根節(jié)點(diǎn)添加信息,添加后顯示出結(jié)果xml文件的內(nèi)容
<?xml version="1.0" encoding="GB2312" ?>
<shop>
<name>華聯(lián)</name>
<address>北京長(zhǎng)安街-9999號(hào)</address>
<desc>連鎖超市</desc>
<telphone>123456789</telphone>
<cat id="food">
<goods id="food11">
<name>food11</name>
<price>12.90</price>
</goods>
<goods id="food12">
<name>food12</name>
<price>22.10</price>
<desc creator="hahawen">好東西推薦</desc>
</goods>
</cat>
<cat>
<goods id="tel21">
<name>tel21</name>
<price>1290</price>
</goods>
</cat>
<cat id="coat">
<goods id="coat31">
<name>coat31</name>
<price>112</price>
</goods>
<goods id="coat32">
<name>coat32</name>
<price>45</price>
</goods>
</cat>
<special id="hot">
<goods>
<name>hot41</name>
<price>99</price>
</goods>
</special>
</shop>
下面是通過(guò)getNode()函數(shù),返回某一個(gè)分類(lèi)下的所有商品的信息
商品名:food11
Array
(
[name] => food11
[price] => 12.90
)
Array
(
[id] => food11
)
商品名:food12
Array
(
[name] => food12
[price] => 22.10
[desc] => Array
(
[value] => 好東西推薦
[attrs] => Array
(
[creator] => hahawen
)
)
)
Array
(
[id] => food12
)
下面是通過(guò)findNodeByPath()函數(shù),返回某一商品的信息
商品名:food11
Array
(
[name] => food11
[price] => 12.90
)
Array
(
[id] => food11
)
下面是通過(guò)setValue()函數(shù),給商品"food11"添加屬性, 然后顯示添加后的結(jié)果
<?xml version="1.0" encoding="GB2312" ?>
<shop>
<name>華聯(lián)</name>
<address>北京長(zhǎng)安街-9999號(hào)</address>
<desc>連鎖超市</desc>
<telphone>123456789</telphone>
<cat id="food">
<goods id="food11">
<name>food11</name>
<price>12.90</price>
<leaveword author="hahawen" date="2004-12-05">這個(gè)商品不錯(cuò)</leaveword>
</goods>
<goods id="food12">
<name>food12</name>
<price>22.10</price>
<desc creator="hahawen">好東西推薦</desc>
</goods>
</cat>
<cat>
<goods id="tel21">
<name>tel21</name>
<price>1290</price>
</goods>
</cat>
<cat id="coat">
<goods id="coat31">
<name>coat31</name>
<price>112</price>
</goods>
<goods id="coat32">
<name>coat32</name>
<price>45</price>
</goods>
</cat>
<special id="hot">
<goods>
<name>hot41</name>
<price>99</price>
</goods>
</special>
</shop>
下面是通過(guò)removeValue()/removeAttribute()函數(shù),給商品"food11"改變和刪除屬性, 然后顯示操作后的結(jié)果
<?xml version="1.0" encoding="GB2312" ?>
<shop>
<name>華聯(lián)</name>
<address>北京長(zhǎng)安街-9999號(hào)</address>
<desc>連鎖超市</desc>
<telphone>123456789</telphone>
<cat id="food">
<goods id="food11">
<name>food11</name>
<price>12.90</price>
<leaveword author="hahawen" date="2004-12-05">這個(gè)商品不錯(cuò)</leaveword>
</goods>
<goods id="food12">
<name>new food12</name>
<price>22.10</price>
</goods>
</cat>
<cat>
<goods id="tel21">
<name>tel21</name>
<price>1290</price>
</goods>
</cat>
<cat id="coat">
<goods id="coat31">
<name>coat31</name>
<price>112</price>
</goods>
<goods id="coat32">
<name>coat32</name>
<price>45</price>
</goods>
</cat>
<special id="hot">
<goods>
<name>hot41</name>
<price>99</price>
</goods>
</special>
</shop>
下面是通過(guò)createNode()函數(shù),添加商品, 然后顯示添加后的結(jié)果
<?xml version="1.0" encoding="GB2312" ?>
<shop>
<name>華聯(lián)</name>
<address>北京長(zhǎng)安街-9999號(hào)</address>
<desc>連鎖超市</desc>
<telphone>123456789</telphone>
<cat id="food">
<goods id="food11">
<name>food11</name>
<price>12.90</price>
<leaveword author="hahawen" date="2004-12-05">這個(gè)商品不錯(cuò)</leaveword>
</goods>
<goods id="food12">
<name>new food12</name>
<price>22.10</price>
</goods>
<goods id="food13">
<name>food13</name>
<price>100</price>
</goods>
</cat>
<cat>
<goods id="tel21">
<name>tel21</name>
<price>1290</price>
</goods>
</cat>
<cat id="coat">
<goods id="coat31">
<name>coat31</name>
<price>112</price>
</goods>
<goods id="coat32">
<name>coat32</name>
<price>45</price>
</goods>
</cat>
<special id="hot">
<goods>
<name>hot41</name>
<price>99</price>
</goods>
</special>
</shop>
下面是通過(guò)removeNode()函數(shù),刪除商品, 然后顯示刪除后的結(jié)果
<?xml version="1.0" encoding="GB2312" ?>
<shop>
<name>華聯(lián)</name>
<address>北京長(zhǎng)安街-9999號(hào)</address>
<desc>連鎖超市</desc>
<telphone>123456789</telphone>
<cat id="food">
<goods id="food11">
<name>food11</name>
<price>12.90</price>
<leaveword author="hahawen" date="2004-12-05">這個(gè)商品不錯(cuò)</leaveword>
</goods>
<goods id="food13">
<name>food13</name>
<price>100</price>
</goods>
</cat>
<cat>
<goods id="tel21">
<name>tel21</name>
<price>1290</price>
</goods>
</cat>
<cat id="coat">
<goods id="coat31">
<name>coat31</name>
<price>112</price>
</goods>
<goods id="coat32">
<name>coat32</name>
<price>45</price>
</goods>
</cat>
<special id="hot">
<goods>
<name>hot41</name>
<price>99</price>
</goods>
</special>
</shop>
- PHP5中使用DOM控制XML實(shí)現(xiàn)代碼
- php5 and xml示例
- PHP5的XML新特性
- PHP XML操作的各種方法解析(比較詳細(xì))
- php的SimpleXML方法讀寫(xiě)XML接口文件實(shí)例解析
- php解析xml方法實(shí)例詳解
- PHP用SAX解析XML的實(shí)現(xiàn)代碼與問(wèn)題分析
- PHP 以POST方式提交XML、獲取XML,解析XML詳解及實(shí)例
- 使用PHP DOM-XML創(chuàng)建和解析XML文件
- 解析php DOMElement 操作xml 文檔的實(shí)現(xiàn)代碼
- php解析xml 的四種簡(jiǎn)單方法(附實(shí)例)
- PHP XML數(shù)據(jù)解析代碼
- PHP4和PHP5版本下解析XML文檔的操作方法實(shí)例分析
相關(guān)文章
Windows環(huán)境下安裝PHP Pear的方法圖文教程
這篇文章主要介紹了Windows環(huán)境下安裝PHP Pear的方法,結(jié)合圖文形式詳細(xì)說(shuō)明了Windows環(huán)境下安裝PHP Pear的相關(guān)命令與操作技巧,需要的朋友可以參考下2019-07-07php 數(shù)組動(dòng)態(tài)添加實(shí)現(xiàn)代碼(最土團(tuán)購(gòu)系統(tǒng)的價(jià)格排序)
最近在實(shí)現(xiàn)最土團(tuán)購(gòu)系統(tǒng)的價(jià)格排序功能,需要對(duì)$oc數(shù)組進(jìn)行擴(kuò)展,經(jīng)過(guò)測(cè)試用下面的方法即可。2011-12-12解析使用ThinkPHP應(yīng)該掌握的調(diào)試手段
本篇文章是對(duì)使用ThinkPHP應(yīng)該掌握的調(diào)試手段進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06