XmlNode.class.php 7.35 KB
<?php
/**
 * XML节点存储对象 用来存储DOM中节点数据,由此可以实现DOM持久化
 * 
 * @name Util_Common_Xml_XmlNode
 * @version version (2009-3-5 上午09:52:42)
 * @package Q.Common.Xml
 * @author peter.zyliu liuziyang@zadooo.com
 * @since 1.0
 */
class Util_Common_Xml_XmlNode {
	private $name;
	private $value;
	private $type;
	private $parentNode;
	private $attributeMap = array ();
	private $children = array ();
	/**
	 * 当前DOM节点
	 *
	 * @var DOMNode
	 */
	private $domNode;
	/**
	 * Enter description here...
	 *
	 * @var Util_Common_Xml_Document
	 */
	private $document;
	
	private $ns = array ();
	
	/**
	 * 构造器
	 *
	 * @param string|DOMNode $xml XML字符串或DOM节点
	 * @param Util_Common_Xml_Document|null $document 所属文档
	 */
	public function __construct($xml = null, Util_Common_Xml_Document $document = null) {
		if ($xml) {
			if (is_string ( $xml )) {
				$this->load ( $xml );
			} elseif ($this->if_is_instance_of ( $xml, "DOMNode" )) {
				$this->loadDOM ( $xml );
			}
		}
		if ($document) {
			$this->document = $document;
		}
	}
	
	/**
	 * 添加新属性
	 *
	 * @param string $name 属性名
	 * @param string $value 属性值
	 */
	public function addAttr($name, $value) {
		$this->attributeMap [$name] = $value;
	}
	
	/**
	 * 添加子节点
	 *
	 * @param Util_Common_Xml_XmlNode $childNode 新的子节点
	 */
	public function addChild(Util_Common_Xml_XmlNode $childNode) {
		$this->children [] = $childNode;
	}
	
	/**
	 * 取得属性值
	 *
	 * @param string $name 属性名
	 * @return string|null
	 */
	public function attr($name) {
		if (isset ( $this->attributeMap [$name] )) {
			return $this->attributeMap [$name];
		}
		return null;
	}
	
	/**
	 * 取得所有属性
	 *
	 * @return array
	 * @see attrs
	 * @deprecated 该函数被attrs()所替代
	 */
	public function attrMap() {
		return $this->attributeMap;
	}
	
	/**
	 * 取得所有属性的名值对
	 *
	 * @return array
	 */
	function attrs() {
		return $this->attrMap ();
	}
	
	/**
	 * 使用名字取得对应的节点
	 *
	 * @param string $childName 子节点名
	 * @param boolean $caseSensitive 是否大小写敏感
	 * @return array
	 */
	public function namedChildren($childName, $caseSensitive = true) {
		$children = array ();
		foreach ( $this->children as $node ) {
			$nodeName = $node->name ();
			if (($caseSensitive && $nodeName === $childName) || (! $caseSensitive && strcasecmp ( $nodeName, $childName ) == 0)) {
				$children [] = $node;
			}
		}
		return $children;
	}
	
	/**
	 * 取得所有子节点
	 *
	 * @return array
	 */
	public function children() {
		return $this->children;
	}
	
	/**
	 * 取得节点名
	 *
	 * @return string
	 */
	public function name() {
		return $this->name;
	}
	
	/**
	 * 取得父节点
	 *
	 * @return Util_Common_Xml_XmlNode
	 */
	public function parent() {
		return $this->parentNode;
	}
	
	/**
	 * 取得节点类型
	 *
	 * @return string
	 */
	public function type() {
		return $this->type;
	}
	
	/**
	 * 取得节点值
	 *
	 * @return string
	 */
	public function value() {
		return $this->value;
	}
	
	/**
	 * 设置节点名
	 *
	 * @param string $name 节点名
	 */
	public function setName($name) {
		$this->name = $name;
	}
	
	/**
	 * 设置节点类型
	 *
	 * @param string $type 节点类型
	 */
	public function setType($type) {
		$this->type = $type;
	}
	
	/**
	 * 节点值
	 *
	 * @param string $value 节点值
	 */
	public function setValue($value) {
		$this->value = $value;
	}
	
	/**
	 * 设置父节点
	 *
	 * @param Util_Common_Xml_XmlNode $parentNode 父节点
	 */
	public function setParent(Util_Common_Xml_XmlNode $parentNode) {
		$this->parentNode = $parentNode;
	}
	
	/**
	 * 判断一个对象/类是否是一个类的实例
	 *
	 * @param object|string $object 对象或类名
	 * @param string $class 类名
	 * @return boolean
	 */
	public function if_is_instance_of($object, $class) {
		if (! is_object ( $object ) && ! is_string ( $object )) {
			return false;
		}
		return ($object instanceof $class);
	}
	
	/**
	 * 从DOM节点中加载Util_Common_Xml_XmlNode节点树
	 *
	 * @param DOMNode $domNode DOM节点
	 */
	public function loadDOM(DOMNode $domNode) {
		if (! $this->document && $this->if_is_instance_of ( $domNode, "Util_Common_Xml_Document" )) {
			$this->setDocument ( new Util_Common_Xml_Document ( $domNode ) );
		}
		$this->domNode = $domNode;
		$this->setType ( $domNode->nodeType );
		$this->setName ( $domNode->nodeName );
		$this->setValue ( $domNode->nodeValue );
		if ($domNode->hasAttributes ()) {
			$attributes = $domNode->attributes;
			foreach ( $attributes as $attribute ) {
				$this->addAttr ( $attribute->nodeName, $attribute->nodeValue );
			}
		}
		if ($domNode->hasChildNodes ()) {
			$childNodes = $domNode->childNodes;
			foreach ( $childNodes as $childNode ) {
				if ($childNode->nodeType == XML_ELEMENT_NODE) {
					$child = new Util_Common_Xml_XmlNode ( $childNode, $this->document );
					$child->setParent ( $this );
					$this->addChild ( $child );
				}
			}
		}
	}
	
	/**
	 * 从XML字符串中加载节点树
	 *
	 * @param string $xmlString XML字符串
	 */
	public function load($xmlString) {
		$dom = new DOMDocument ( );
		$dom->loadXML ( $xmlString );
		$this->setDocument ( new Util_Common_Xml_Document ( $dom ) );
		$this->loadDOM ( $dom );
	}
	
	/**
	 * 根据xpath表达式查找节点
	 *
	 * @param string|integer $expr xpath表达式或者子节点索引
	 * @return Util_Common_Xml_XmlNode
	 */
	function find($expr) {
		if (is_int ( $expr )) {
			return isset ( $this->children [$expr] ) ? $this->children [$expr] : null;
		}
		$nodes = $this->findAll ( $expr );
		return empty ( $nodes ) ? null : $nodes [0];
	}
	
	/**
	 * 根据xpath表达式查找节点
	 *
	 * @param string $expr 表达式
	 * @return array
	 */
	function findAll($expr) {
		$xpath = new DOMXPath ( $this->document->dom () );
		foreach ( $this->document->ns () as $prefix => $uri ) {
			$xpath->registerNamespace ( $prefix, $uri );
		}
		$nodeList = $xpath->query ( $expr, $this->domNode );
		$ret = array ();
		for($i = 0; $i < $nodeList->length; $i ++) {
			$node = $nodeList->item ( $i );
			$ret [] = new Util_Common_Xml_XmlNode ( $node, $this->document );
		}
		return $ret;
	}
	
	/**
	 * 查找和当前节点相邻的下一个节点
	 *
	 * @return Util_Common_Xml_XmlNode
	 */
	function next() {
		$current = $this->domNode;
		while ( $next = $current->nextSibling ) {
			if ($next->nodeType == XML_ELEMENT_NODE) {
				return new Util_Common_Xml_XmlNode ( $next, $this->document );
			}
			$current = $next;
		}
		return null;
	}
	
	/**
	 * 查找和当前节点相邻的上一个节点
	 *
	 * @return Util_Common_Xml_XmlNode
	 */
	function prev() {
		$current = $this->domNode;
		while ( $prev = $current->previousSibling ) {
			if ($prev->nodeType == XML_ELEMENT_NODE) {
				return new Util_Common_Xml_XmlNode ( $prev, $this->document );
			}
			$current = $prev;
		}
		return null;
	}
	
	/**
	 * 将当前节点转化为XML字符串
	 *
	 * @return string
	 */
	function asXml() {
		if ($this->document) {
			return $this->document->dom ()->saveXML ( $this->domNode );
		}
		return null;
	}
	
	/**
	 * 设置当前节点所在文档
	 *
	 * @param Util_Common_Xml_Document $document 文档
	 */
	function setDocument(Util_Common_Xml_Document $document) {
		$this->document = $document;
	}
	
	/**
	 * 获取当前节点所在文档
	 *
	 * @return IXmlDocument 文档
	 * @since 1.0.1
	 */
	function document() {
		return $this->document;
	}
}
?>