<?php
|
|
|
|
/*
|
|
This file is part of ActiveLink PHP XML Package (www.active-link.com).
|
|
Copyright (c) 2002-2004 by Zurab Davitiani
|
|
|
|
You can contact the author of this software via E-mail at
|
|
hattrick@mailcan.com
|
|
|
|
ActiveLink PHP XML Package is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
(at your option) any later version.
|
|
|
|
ActiveLink PHP XML Package is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with ActiveLink PHP XML Package; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
import("org.active-link.xml.Tag");
|
|
import("org.active-link.xml.Tree");
|
|
|
|
/**
|
|
* XML class provides a tree-like structure to read/write/modify XML
|
|
* @class XML
|
|
* @package org.active-link.xml
|
|
* @author Zurab Davitiani
|
|
* @version 0.4.0
|
|
* @extends Tree
|
|
* @requires Tag, Tree, XMLBranch, XMLLeaf
|
|
* @see Tree
|
|
*/
|
|
|
|
class XML extends Tree {
|
|
|
|
// protected variables
|
|
var $tag;
|
|
var $pathSeparator;
|
|
|
|
/**
|
|
* If argument is an XML String it parses the string into XML object
|
|
* If argument is a tag path, creates appropriate branches and tags
|
|
* If argument is a simple string then sets that as a root tag name
|
|
* @method XML
|
|
* @param optional string argument
|
|
* @returns none
|
|
*/
|
|
function XML($argument = "") {
|
|
$success = false;
|
|
$this->Tree();
|
|
$this->pathSeparator = "/";
|
|
$this->tag = new Tag();
|
|
if(is_string($argument)) {
|
|
// if this is an XML string to be parsed
|
|
if(strpos($argument, $this->tag->tagEndOpen) > 0 || strpos($argument, $this->tag->tagClose) > 0)
|
|
$this->parseFromString($argument);
|
|
// else if this is a tag path to be created
|
|
elseif(strpos($argument, $this->pathSeparator) > 0) {
|
|
$tags = explode($this->pathSeparator, $argument);
|
|
$this->tag->setTagName($tags[0]);
|
|
$this->setTagContent("", $argument);
|
|
}
|
|
else
|
|
$this->tag->setTagName($argument);
|
|
$success = true;
|
|
}
|
|
else
|
|
$success = false;
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Adds another XML tree as a branch to the current XML object
|
|
* @method addXMLAsBranch
|
|
* @param object xml
|
|
* @param optional mixed id
|
|
* @returns true if successful, false otherwise
|
|
*/
|
|
function addXMLAsBranch($xml, $id = -1) {
|
|
$success = false;
|
|
if(is_object($xml) && strtolower(get_class($xml)) == "xml") {
|
|
$newBranch = new XMLBranch();
|
|
$newBranch->nodes = $xml->nodes;
|
|
$newBranch->tag = $xml->tag;
|
|
$success = $this->addXMLBranch($newBranch, $id);
|
|
}
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Adds XML Branch to the current XML object
|
|
* @method addXMLBranch
|
|
* @param object xmlBranch
|
|
* @param optional mixed id
|
|
* @returns true if successful, false otherwise
|
|
*/
|
|
function addXMLBranch($xmlBranch, $id = -1) {
|
|
$success = false;
|
|
if(is_object($xmlBranch) && strtolower(get_class($xmlBranch)) == "xmlbranch") {
|
|
$xmlBranch->setParentXML($this);
|
|
$success = $this->addNode($id, $xmlBranch);
|
|
}
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Adds XML Leaf to the current XML object
|
|
* @method addXMLLeaf
|
|
* @param object xmlLeaf
|
|
* @param optional mixed id
|
|
* @returns true if successful, false otherwise
|
|
*/
|
|
function addXMLLeaf($xmlLeaf, $id = -1) {
|
|
$success = false;
|
|
if(is_object($xmlLeaf) && strtolower(get_class($xmlLeaf)) == "xmlleaf") {
|
|
$xmlLeaf->setParentXML($this);
|
|
$success = $this->addNode($id, $xmlLeaf);
|
|
}
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Retrieves an array of references to XMLBranches within the specified path, tag name, attribute name, and attribute value
|
|
* @method getBranches
|
|
* @param optional string tagPath
|
|
* @param optional string tagName
|
|
* @param optional string attrName
|
|
* @param optional string attrValue
|
|
* @returns array of references to XMLBranch objects that meet specified criteria, or false if none found
|
|
*/
|
|
function getBranches($tagPath = "", $tagName = "", $attrName = "", $attrValue = "") {
|
|
$branchArray = array();
|
|
if($tagPath == "")
|
|
$tagPath = $this->tag->getTagName();
|
|
$tags = explode($this->pathSeparator, $tagPath);
|
|
if($this->tag->getTagName() == $tags[0]) {
|
|
if(count($tags) == 1) {
|
|
$arrKeys = array_keys($this->nodes);
|
|
for($index = 0; $index < count($arrKeys); $index ++) {
|
|
if(gettype($this->nodes[$arrKeys[$index]]) == "object" && strtolower(get_class($this->nodes[$arrKeys[$index]])) == "xmlbranch") {
|
|
if(($tagName == "" || $this->nodes[$arrKeys[$index]]->tag->getTagName() == $tagName) &&
|
|
($attrName == "" || $this->nodes[$arrKeys[$index]]->tag->attributeExists($attrName)) &&
|
|
($attrValue == "" || $this->nodes[$arrKeys[$index]]->tag->getTagAttribute($attrName) == $attrValue)) {
|
|
$branchArray[] = &$this->nodes[$arrKeys[$index]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
$arrKeys = array_keys($this->nodes);
|
|
for($index = 0; $index < count($arrKeys); $index ++) {
|
|
if(gettype($this->nodes[$arrKeys[$index]]) == "object" && strtolower(get_class($this->nodes[$arrKeys[$index]])) == "xmlbranch") {
|
|
if($this->nodes[$arrKeys[$index]]->tag->getTagName() == $tags[1]) {
|
|
$newTagPath = implode($this->pathSeparator, array_slice($tags, 1));
|
|
$newArray = $this->nodes[$arrKeys[$index]]->getBranches($newTagPath, $tagName, $attrName, $attrValue);
|
|
if($newArray !== false)
|
|
$branchArray = array_merge($branchArray, $newArray);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(count($branchArray) == 0)
|
|
$branchArray = false;
|
|
return $branchArray;
|
|
}
|
|
|
|
/**
|
|
* Retrieves an array of references to XMLLeaf(s) within the specified path
|
|
* @method getLeafs
|
|
* @param optional string tagPath
|
|
* @returns array of references to XMLLeaf objects in specified tag path, false if none found
|
|
*/
|
|
function getLeafs($tagPath = "") {
|
|
$leafArray = array();
|
|
if($tagPath == "")
|
|
$tagPath = $this->tag->getTagName();
|
|
$tags = explode($this->pathSeparator, $tagPath);
|
|
if($this->tag->getTagName() == $tags[0]) {
|
|
if(count($tags) == 1) {
|
|
$arrKeys = array_keys($this->nodes);
|
|
for($index = 0; $index < count($arrKeys); $index ++) {
|
|
if(gettype($this->nodes[$arrKeys[$index]]) == "object" && strtolower(get_class($this->nodes[$arrKeys[$index]])) == "xmlleaf") {
|
|
$leafArray[] = &$this->nodes[$arrKeys[$index]];
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
$arrKeys = array_keys($this->nodes);
|
|
for($index = 0; $index < count($arrKeys); $index ++) {
|
|
if(gettype($this->nodes[$arrKeys[$index]]) == "object" && strtolower(get_class($this->nodes[$arrKeys[$index]])) == "xmlbranch") {
|
|
if($this->nodes[$arrKeys[$index]]->tag->getTagName() == $tags[1]) {
|
|
$newTagPath = implode($this->pathSeparator, array_slice($tags, 1));
|
|
$newArray = $this->nodes[$arrKeys[$index]]->getLeafs($newTagPath);
|
|
if($newArray !== false)
|
|
$leafArray = array_merge($leafArray, $newArray);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(count($leafArray) == 0)
|
|
$leafArray = false;
|
|
return $leafArray;
|
|
}
|
|
|
|
/**
|
|
* Returns attribute value of the specified tag and tagpath
|
|
* @method getTagAttribute
|
|
* @param string attributeName
|
|
* @param optional string tagPath
|
|
* @returns attribute of the specified tag if successful, false otherwise
|
|
*/
|
|
function getTagAttribute($attributeName, $tagPath = "") {
|
|
if($tagPath == "")
|
|
$tagPath = $this->tag->getTagName();
|
|
$tags = explode($this->pathSeparator, $tagPath);
|
|
$attributeValue = false;
|
|
if($this->tag->getTagName() == $tags[0]) {
|
|
if(sizeof($tags) == 1) {
|
|
if($this->tag->attributeExists($attributeName))
|
|
$attributeValue = $this->tag->getTagAttribute($attributeName);
|
|
}
|
|
else {
|
|
foreach($this->nodes as $node) {
|
|
if(strtolower(get_class($node)) == "xmlbranch")
|
|
if($node->tag->getTagName() == $tags[1]) {
|
|
$newTagPath = implode($this->pathSeparator, array_slice($tags, 1));
|
|
$attributeValue = $node->getTagAttribute($attributeName, $newTagPath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $attributeValue;
|
|
}
|
|
|
|
/**
|
|
* Returns contents of the specified tag path
|
|
* @method getTagContent
|
|
* @param optional string tagPath
|
|
* @returns content of the tag from the specified path if successful, false otherwise
|
|
*/
|
|
function getTagContent($tagPath = "") {
|
|
if($tagPath == "")
|
|
$tagPath = $this->tag->getTagName();
|
|
$tags = explode($this->pathSeparator, $tagPath);
|
|
$tagValue = false;
|
|
if($this->tag->getTagName() == $tags[0]) {
|
|
if(sizeof($tags) == 1)
|
|
$tagValue = $this->getXMLContent();
|
|
else {
|
|
foreach($this->nodes as $node) {
|
|
if(strtolower(get_class($node)) == "xmlbranch")
|
|
if($node->tag->getTagName() == $tags[1]) {
|
|
$newTagPath = implode($this->pathSeparator, array_slice($tags, 1));
|
|
$tagValue = $node->getTagContent($newTagPath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $tagValue;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the tag name of the current object
|
|
* @method getTagName
|
|
* @returns tag name
|
|
*/
|
|
function getTagName() {
|
|
return($this->tag->getTagName());
|
|
}
|
|
|
|
/**
|
|
* Gets contents from the current object
|
|
* @method getXMLContent
|
|
* @returns contents of the current XML tag
|
|
*/
|
|
function getXMLContent() {
|
|
$xmlContent = "";
|
|
foreach($this->nodes as $node) {
|
|
if(gettype($node) == "object") {
|
|
if(strtolower(get_class($node)) == "xmlbranch")
|
|
$xmlContent .= $node->getXMLString();
|
|
elseif(strtolower(get_class($node)) == "xmlleaf")
|
|
$xmlContent .= $node->getValue();
|
|
}
|
|
}
|
|
return $xmlContent;
|
|
}
|
|
|
|
/**
|
|
* Gets the whole XML string of the current object
|
|
* @method getXMLString
|
|
* @param optional mixed indent
|
|
* @returns complete XML string of current object
|
|
*/
|
|
function getXMLString($indent = false) {
|
|
$xmlString = "";
|
|
$containsBranches = false;
|
|
$containsLeafs = false;
|
|
$newIndent = false;
|
|
if($indent === false)
|
|
$newIndent = false;
|
|
else {
|
|
$newIndent = $indent + 1;
|
|
$this->tag->setTagFormat($this->tag->FORMAT_INDENT, $indent);
|
|
}
|
|
foreach($this->nodes as $node) {
|
|
if(gettype($node) == "object") {
|
|
if(strtolower(get_class($node)) == "xmlbranch") {
|
|
$this->tag->tagContent .= $node->getXMLString($newIndent);
|
|
$containsBranches = true;
|
|
}
|
|
elseif(strtolower(get_class($node)) == "xmlleaf") {
|
|
$this->tag->tagContent .= $node->getValue();
|
|
$containsLeafs = true;
|
|
}
|
|
}
|
|
}
|
|
if($containsBranches)
|
|
$this->tag->setTagFormatEndTag(true);
|
|
$xmlString = $this->tag->getTagString();
|
|
$this->tag->setTagContent("");
|
|
return $xmlString;
|
|
}
|
|
|
|
/**
|
|
* Find out whether the current object has any branches
|
|
* @method hasBranch
|
|
* @returns true if branches exist, false otherwise
|
|
*/
|
|
function hasBranch() {
|
|
$hasBranch = false;
|
|
foreach($this->nodes as $node) {
|
|
if(strtolower(get_class($node)) == "xmlbranch") {
|
|
$hasBranch = true;
|
|
break;
|
|
}
|
|
}
|
|
return $hasBranch;
|
|
}
|
|
|
|
/**
|
|
* Find out whether the current object has any leaf(s)
|
|
* @method hasLeaf
|
|
* @returns true if leaf(s) exist, false otherwise
|
|
*/
|
|
function hasLeaf() {
|
|
$hasLeaf = false;
|
|
foreach($this->nodes as $node) {
|
|
if(strtolower(get_class($node)) == "xmlleaf") {
|
|
$hasLeaf = true;
|
|
break;
|
|
}
|
|
}
|
|
return $hasLeaf;
|
|
}
|
|
|
|
/**
|
|
* Parse entire XML string into the current object; also called from constructor
|
|
* @method parseFromString
|
|
* @param string parseString
|
|
* @returns none
|
|
*/
|
|
function parseFromString($parseString) {
|
|
$tagResult = $this->tag->setTagFromString($parseString);
|
|
if($tagResult !== false) {
|
|
$this->parseNodesFromTag();
|
|
$this->tag->setTagContent("");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parses the current tag content into Branches and Leaf(s); called from parseFromString
|
|
* @method parseNodesFromTag
|
|
* @returns none
|
|
*/
|
|
function parseNodesFromTag() {
|
|
$tempTag = new Tag();
|
|
$parseString = $this->tag->getTagContent();
|
|
while($tagParsed = $tempTag->setTagFromString($parseString)) {
|
|
if($tagParsed[0] != 0 && trim(substr($parseString, 0, $tagParsed[0]) != ""))
|
|
$this->addXMLLeaf(new XMLLeaf(trim(substr($parseString, 0, $tagParsed[0]))));
|
|
$branch = new XMLBranch();
|
|
$tempTagCopy = new Tag();
|
|
$tempTagCopy->setTagName($tempTag->getTagName());
|
|
$tempTagCopy->tagAttributes = $tempTag->tagAttributes;
|
|
$tempTagCopy->setTagContent($tempTag->getTagContent());
|
|
$branch->setTag($tempTagCopy);
|
|
$branch->parseNodesFromTag();
|
|
$branch->tag->setTagContent("");
|
|
$this->addXMLBranch($branch);
|
|
$parseString = trim(substr($parseString, $tagParsed[1]));
|
|
}
|
|
if(strlen($parseString) > 0 && trim($parseString) != "")
|
|
$this->addXMLLeaf(new XMLLeaf($parseString));
|
|
}
|
|
|
|
/**
|
|
* Removes all Branches from current object
|
|
* @method removeAllBranches
|
|
*/
|
|
function removeAllBranches() {
|
|
foreach($this->nodes as $key => $value) {
|
|
if(strtolower(get_class($value)) == "xmlbranch")
|
|
unset($this->nodes[$key]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes all Leaf(s) from current object
|
|
* @method removeAllLeafs
|
|
*/
|
|
function removeAllLeafs() {
|
|
foreach($this->nodes as $key => $value) {
|
|
if(strtolower(get_class($value)) == "xmlleaf")
|
|
unset($this->nodes[$key]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes Branches with the specified criteria
|
|
* @method removeBranches
|
|
* @param optional string tagPath
|
|
* @param optional string tagName
|
|
* @param optional string attrName
|
|
* @param optional string attrValue
|
|
* @returns number of branches deleted
|
|
*/
|
|
function removeBranches($tagPath = "", $tagName = "", $attrName = "", $attrValue = "") {
|
|
$branchesDeleted = 0;
|
|
$referencedBranches = array();
|
|
$tags = explode($this->pathSeparator, $tagPath);
|
|
if(count($tags) > 1) {
|
|
$parentTagName = array_pop($tags);
|
|
$parentTagPath = implode($this->pathSeparator, $tags);
|
|
$referencedBranches = $this->getBranches($parentTagPath, $parentTagName);
|
|
}
|
|
else {
|
|
$referencedBranches[] = &$this;
|
|
}
|
|
for($i = 0; $i < count($referencedBranches); $i ++) {
|
|
$arrKeys = array_keys($referencedBranches[$i]->nodes);
|
|
for($index = 0; $index < count($arrKeys); $index ++) {
|
|
if(gettype($referencedBranches[$i]->nodes[$arrKeys[$index]]) == "object" && strtolower(get_class($referencedBranches[$i]->nodes[$arrKeys[$index]])) == "xmlbranch") {
|
|
if(($tagName == "" || $referencedBranches[$i]->nodes[$arrKeys[$index]]->tag->getTagName() == $tagName) &&
|
|
($attrName == "" || $referencedBranches[$i]->nodes[$arrKeys[$index]]->tag->attributeExists($attrName)) &&
|
|
($attrValue == "" || $referencedBranches[$i]->nodes[$arrKeys[$index]]->tag->getTagAttribute($attrName) == $attrValue)) {
|
|
$referencedBranches[$i]->removeNode($arrKeys[$index]);
|
|
$branchesDeleted ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $branchesDeleted;
|
|
}
|
|
|
|
/**
|
|
* Sets tag object of a branch specified by branch ID for the current object; see getBranches and setTag
|
|
* @method setBranchTag
|
|
* @param mixed branchId
|
|
* @param object tag
|
|
* @returns true on success, false otherwise
|
|
*/
|
|
function setBranchTag($branchId, $tag) {
|
|
$success = true;
|
|
if(strtolower(get_class($this->nodes[$branchId])) == "xmlbranch" && strtolower(get_class($tag)) == "tag")
|
|
$this->nodes[$branchId]->setTag($tag);
|
|
else
|
|
$success = false;
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Sets tag object of the current object
|
|
* @method setTag
|
|
* @param object tag
|
|
* @returns true if successful, false otherwise
|
|
*/
|
|
function setTag($tag) {
|
|
$success = true;
|
|
if(strtolower(get_class($tag)) == "tag")
|
|
$this->tag = $tag;
|
|
else
|
|
$success = false;
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Sets an attribute name and value on an existing tag found via tagpath string
|
|
* @method setTagAttribute
|
|
* @param string attributeName
|
|
* @param optional string attributeValue
|
|
* @param optional string tagPath
|
|
* @returns true if successful, false otherwise
|
|
*/
|
|
function setTagAttribute($attributeName, $attributeValue = "", $tagPath = "") {
|
|
if($tagPath == "")
|
|
$tagPath = $this->tag->getTagName();
|
|
$success = true;
|
|
$tags = explode($this->pathSeparator, $tagPath);
|
|
if($this->tag->getTagName() == $tags[0]) {
|
|
if(sizeof($tags) == 1)
|
|
$this->tag->setAttribute($attributeName, $attributeValue);
|
|
else {
|
|
$nodeTagFound = false;
|
|
reset($this->nodes);
|
|
$arrKeys = array_keys($this->nodes);
|
|
for($index = 0; $index < count($arrKeys); $index ++) {
|
|
$node =& $this->nodes[$arrKeys[$index]];
|
|
if(strtolower(get_class($node)) == "xmlbranch")
|
|
if($node->tag->getTagName() == $tags[1]) {
|
|
$newTagPath = implode($this->pathSeparator, array_slice($tags, 1));
|
|
$success = $node->setTagAttribute($attributeName, $attributeValue, $newTagPath);
|
|
$nodeTagFound = true;
|
|
}
|
|
}
|
|
if(!$nodeTagFound)
|
|
$success = false;
|
|
}
|
|
}
|
|
else
|
|
$success = false;
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Sets content of the specified tag
|
|
* @method setTagContent
|
|
* @param mixed content
|
|
* @param optional string tagPath
|
|
* @returns true if successful, false otherwise
|
|
*/
|
|
function setTagContent($content, $tagPath = "") {
|
|
if($tagPath == "")
|
|
$tagPath = $this->tag->getTagName();
|
|
$success = true;
|
|
$tags = explode($this->pathSeparator, $tagPath);
|
|
if($this->tag->getTagName() == $tags[0]) {
|
|
if(sizeof($tags) == 1) {
|
|
//$this->nodes = array(new XMLLeaf($content));
|
|
$this->removeAllNodes();
|
|
$this->addXMLLeaf(new XMLLeaf($content));
|
|
}
|
|
else {
|
|
$nodeTagFound = false;
|
|
reset($this->nodes);
|
|
$arrKeys = array_keys($this->nodes);
|
|
for($index = 0; $index < count($arrKeys); $index ++) {
|
|
$node =& $this->nodes[$arrKeys[$index]];
|
|
if(strtolower(get_class($node)) == "xmlbranch")
|
|
if($node->tag->getTagName() == $tags[1]) {
|
|
$newTagPath = implode($this->pathSeparator, array_slice($tags, 1));
|
|
$success = $node->setTagContent($content, $newTagPath);
|
|
$nodeTagFound = true;
|
|
}
|
|
}
|
|
if(!$nodeTagFound) {
|
|
$branch = new XMLBranch();
|
|
$branch->setTag(new Tag($tags[1]));
|
|
$newTagPath = implode($this->pathSeparator, array_slice($tags, 1));
|
|
$branch->setTagContent($content, $newTagPath);
|
|
$this->addXMLBranch($branch);
|
|
}
|
|
}
|
|
}
|
|
return $success;
|
|
}
|
|
|
|
}
|
|
|
|
import("org.active-link.xml.XMLBranch");
|
|
import("org.active-link.xml.XMLLeaf");
|
|
|
|
?>
|