<?php
/***************************************************************************
*
* IMPORTANT: This is a commercial product made by BoonEx Ltd. and cannot be modified for other than personal usage.
* This product cannot be redistributed for free or a fee without written permission from BoonEx Ltd.
* This notice may not be removed from the source code.
*
***************************************************************************/

/**
 * This class is needed to work with XML files.
 */
class BxXml
{
	function createParser()
	{
		return xml_parser_create("UTF-8");
	}
	
    /**
         * Get the value of specified attribute for specified tag.
         */
	function getAttribute($sXmlContent, $sXmlTag, $sXmlAttribute)
	{
		$rParser = $this->createParser();
		xml_parse_into_struct($rParser, $sXmlContent, $aValues, $aIndexes);
		xml_parser_free($rParser);

		$aFieldIndex = $aIndexes[strtoupper($sXmlTag)][0];
		return $aValues[$aFieldIndex]['attributes'][strtoupper($sXmlAttribute)];
	}
	
	/**
         * Get an array of attributes for specified tag or an array of tags with the same name.
         */
	function getAttributes($sXmlContent, $sXmlTagName, $sXmlTagIndex = -1)
	{
		$rParser = $this->createParser();
		xml_parse_into_struct($rParser, $sXmlContent, $aValues, $aIndexes);
		xml_parser_free($rParser);

		/**
		 * gets two-dimensional array of attributes.
		 * tags-attlibutes
		 */
		if($sXmlTagIndex == -1)
		{
			$aResult = array();
			$aTagIndexes = $aIndexes[strtoupper($sXmlTagName)];
			if(count($aTagIndexes) <= 0) return NULL;
			foreach($aTagIndexes as $iTagIndex)
				$aResult[] = $aValues[$iTagIndex]['attributes'];
			return $aResult;
		}
		else
		{
			$iTagIndex = $aIndexes[strtoupper($sXmlTagName)][$sXmlTagIndex];
			return $aValues[$iTagIndex]['attributes'];
		}
	}

	/**
         * Get an array of tags or one tag if its index is specified.
         */
	function getTags($sXmlContent, $sXmlTagName, $iXmlTagIndex = -1)
	{
		$rParser = $this->createParser();
		xml_parse_into_struct($rParser, $sXmlContent, $aValues, $aIndexes);
		xml_parser_free($rParser);

		//--- Get an array of tags ---//
		if($iXmlTagIndex == -1)
		{
			$aResult = array();
			$aTagIndexes = $aIndexes[strtoupper($sXmlTagName)];
			if(count($aTagIndexes) <= 0) return NULL;
			foreach($aTagIndexes as $iTagIndex)
				$aResult[] = $aValues[$iTagIndex];
			return $aResult;
		}
		else
		{
			$iTagIndex = $aIndexes[strtoupper($sXmlTagName)][$iXmlTagIndex];
			return $aValues[$iTagIndex];
		}
	}

	/**
         * Gets the values of the given tag.
         */
	function getValues($sXmlContent, $sXmlTagName)
	{
		$rParser = $this->createParser();
		xml_parse_into_struct($rParser, $sXmlContent, $aValues, $aIndexes);
		xml_parser_free($rParser);

		$aTagIndexes = $aIndexes[strtoupper($sXmlTagName)];
		$aTagIndexes = isset($aTagIndexes) ? $aTagIndexes : array();
		$aReturnValues = array();
		foreach($aTagIndexes as $iTagIndex) {
            $aReturnValues[$aValues[$iTagIndex]['attributes']['KEY']] = 
                isset($aValues[$iTagIndex]['value']) ? $aValues[$iTagIndex]['value'] : NULL;
        }
		return $aReturnValues;
	}
	
	/**
         * Sets the values of tag where attribute "key" equals to specified.
         */
	function setValues($sXmlContent, $sXmlTagName, $aKeyValues)
	{
		$rParser = $this->createParser();
		xml_parse_into_struct($rParser, $sXmlContent, $aValues, $aIndexes);
		xml_parser_free($rParser);

		$aTagIndexes = $aIndexes[strtoupper($sXmlTagName)];
		if(count($aTagIndexes) == 0) return $this->getContent();
		foreach($aTagIndexes as $iTagIndex)
			foreach($aKeyValues as $sKey => $sValue)
				if($aValues[$iTagIndex]['attributes']['KEY'] == $sKey)
				{
					$aValues[$iTagIndex]['value'] = $sValue;
					break;
				}
		return $this->getContent($aValues);
	}
	
	/**
         * Adds given values to XML content.
         */
	function addValues($sXmlContent, $sXmlTagName, $aKeyValues)
	{
		$rParser = $this->createParser();
		xml_parse_into_struct($rParser, $sXmlContent, $aValues, $aIndexes);
		xml_parser_free($rParser);

		$aTagIndexes = $aIndexes[strtoupper($sXmlTagName)];
		$iLastTagIndex = $aTagIndexes[count($aTagIndexes) - 1];
		$iAddsCount = count($aKeyValues);
		$iLevel = $aValues[$iLastTagIndex]["level"];

		for($i=count($aValues)-1; $i>$iLastTagIndex; $i--)
			$aValues[$i+$iAddsCount] = $aValues[$i];

		$i = $iLastTagIndex;
		foreach($aKeyValues as $sKey => $sValue)
		{
			$i++;
			$aValues[$i] = Array("tag" => $sXmlTagName, "type" => "complete", "level" => $iLevel, "attributes" => Array("KEY" => $sKey), "value" => $sValue);
		}
		return $this->getContent($aValues);
	}

	/**
         * get content in XML format from given values array
         */
	function getContent($aValues = array())
	{
		$sContent = "";
		foreach($aValues as $aValue)
		{
			$sTagName = strtolower($aValue['tag']);
			switch($aValue['type'])
			{
				case "open":
					$sContent .= "<" . $sTagName . ">";
					break;

				case "complete":
					$sContent .= "<" . $sTagName;
					if(isset($aValue['attributes']))
						foreach($aValue['attributes'] as $sAttrKey => $sAttrValue)
							$sContent .= " " . strtolower($sAttrKey) . "=\"" . $sAttrValue . "\"";
					$sContent .= isset($aValue['value']) ? "><![CDATA[" . $aValue['value'] . "]]></" . $sTagName . ">" : " />";
					break;

				case "close":
					$sContent .= "</" . $sTagName . ">";
					break;
			}
		}
		return $sContent;
	}
}

$oXml = new BxXml();

function xmlGetAttribute($sXmlContent, $sXmlTag, $sXmlAttribute)
{
	global $oXml;
	return $oXml->getAttribute($sXmlContent, $sXmlTag, $sXmlAttribute);
}

function xmlGetAttributes($sXmlContent, $sXmlTagName, $sXmlTagIndex = -1)
{
	global $oXml;
	return $oXml->getAttributes($sXmlContent, $sXmlTagName, $sXmlTagIndex);
}

function xmlGetTags($sXmlContent, $sXmlTagName, $iXmlTagIndex = -1)
{
	global $oXml;
	return $oXml->getTags($sXmlContent, $sXmlTagName, $iXmlTagIndex = -1);
}
function xmlGetValue($sXmlContent, $sXmlTagName, $sName)
{
	global $oXml;
	$aValues = $oXml->getValues($sXmlContent, $sXmlTagName);
	return isset($aValues[$sName]) ? $aValues[$sName] : "";
}
function xmlGetValues($sXmlContent, $sXmlTagName)
{
	global $oXml;
	return $oXml->getValues($sXmlContent, $sXmlTagName);
}
function xmlSetValue($sXmlContent, $sXmlTagName, $sName, $sValue)
{
	global $oXml;
	$aKeyValues = Array($sName => $sValue);
	return $oXml->setValues($sXmlContent, $sXmlTagName, $aKeyValues);
}
function xmlSetValues($sXmlContent, $sXmlTagName, $aKeyValues)
{
	global $oXml;
	return $oXml->setValues($sXmlContent, $sXmlTagName, $aKeyValues);
}
function xmlAddValues($sXmlContent, $sXmlTagName, $aKeyValues)
{
	global $oXml;
	return $oXml->addValues($sXmlContent, $sXmlTagName, $aKeyValues);
}