You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

580 lines
18 KiB

<?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");
?>