Файл: core/classes/class.xmlnodex.php
Строк: 250
<?php
$NodeID = 0;
class xmlNodeX{
    
    var $ID;
    var $Name;
    var $Data;
    var $Attributes     = array();
    /**
     * Enter description here...
     *
     * @var xmlNodeX
     */
    var $ParentNode;
    var $ChildNodes     = array();
    var $ParserResource;
    var $parsingNode;
    
    function xmlNodeX($_Name = '', $_Attributes = array(), $_Data = '' ){
        
        $this->Name         = $_Name;
        $this->Attributes     = is_array($_Attributes)?$_Attributes:array();
        $this->Data         = $_Data;
    }
    
    function getName(){
        
        return $this->Name;
    }
    
    function getAttribute($_Name){
        
        if (isset($this->Attributes[$_Name])) {
            
            return $this->Attributes[$_Name];
        }else return null;
    }
    
    function getAttributes(){
        
        return $this->Attributes;
    }
    
    function getData(){
        
        return $this->Data;
    }
    
    function &getChildNodes(){
        
        return $this->ChildNodes;
    }
    
    /**
     * Create child node
     *
     * @param string $_Name
     * @param array $_Attributes
     * @param string $_Data
     * @return xmlNodeX
     */
    function &createChildNode($_Name, $_Attributes = array(), $_Data = ''){
        
        $_ChildNode = &new xmlNodeX($_Name, $_Attributes, $_Data);
        
        $this->addChildNode($_ChildNode);
        return $_ChildNode;
    }
    /**
     * Create child node
     *
     * @param string $_Name
     * @param array $_Attributes
     * @param string $_Data
     * @return xmlNodeX
     */
    function &child($_Name, $_Attributes = array(), $_Data = ''){
        
        $child = &$this->createChildNode($_Name, $_Attributes, $_Data);
        return $child;
    }
        
    /**
     * Enter description here...
     *
     * @param xmlNodeX $_ChildNode
     */
    function addChildNode(&$_ChildNode){
        
        global $NodeID;
        $_ChildNode->ID = ++$NodeID;
        $_ChildNode->setParentNode($this);
        $this->ChildNodes[] = &$_ChildNode;
    }
    
    /**
     * Set parent node
     *
     * @param unknown_type $ParentNode
     */
    function setParentNode(&$ParentNode){
        
        $this->ParentNode = &$ParentNode;
    }
    
    /**
     * Enter description here...
     *
     * @param xmlNodeX $NewParentNode
     */
    function moveNode(&$NewParentNode){
        
        $OldParentNode = &$this->ParentNode;
        $OldParentNode->removeChildNode($this);
        $NewParentNode->addChildNode($this);
    }
    
    /**
     * Remove child node
     *
     * @param xmlNodeX $RemoveNode
     */
    function removeChildNode(&$RemoveNode){
        
        $TC = count($this->ChildNodes);
        for ($i=0;$i<$TC;$i++){
            
            $ChildNode = &$this->ChildNodes[$i];
            /* @var $ChildNode xmlNodeX */
            if($ChildNode->ID == $RemoveNode->ID){
                array_splice($this->ChildNodes, $i, 1);
                unset($RemoveNode->ParentNode);
                break;
            }
        }
    }
    
    /**
     * Return parent node
     *
     * @return xmlNodeX
     */
    function &getParentNode(){
        
        return $this->ParentNode;
    }
    function getNodeXML($_Level = -1, $Tabbed = false, $disableCDATA = false){
        
        $_Level++;
        $_attrs = array();
        foreach ( $this->Attributes as $_Key=>$_Val ){
            
            $_attrs[] = $_Key.'="'.xHtmlSpecialChars($_Val).'"';
        }
        
        $_ChildrenXMLs = array();
        
        $_ChildNodesNum = count($this->ChildNodes);
        foreach ($this->ChildNodes as $i=>$ChildNode){
            
            if(!is_a($this->ChildNodes[$i],'xmlnodex'))continue;
            $_ChildrenXMLs[] = $this->ChildNodes[$i]->getNodeXML($_Level, $Tabbed, $disableCDATA);
        }
            
        return ($Tabbed?str_repeat("n",intval($_Level>0)).str_repeat("t", $_Level):'').
            "<{$this->Name}".(count($_attrs)?" ".implode(" ", $_attrs):'').">".($this->Data?($disableCDATA?$this->Data:"<![CDATA[".($this->Data)."]]>"):"").
            (count($_ChildrenXMLs)?implode("",$_ChildrenXMLs).
            ($Tabbed?"n".str_repeat("t", $_Level):'')
            :'').
            "</{$this->Name}>";
    }
    
    function _replaceSpecialChars($_Data){
    
        $_Data = str_replace('&','&', $_Data);
        return str_replace(array('<','>'), array('<','>'), $_Data);
    }
    function renderTreeFromFile($FileName){
        
        if(!file_exists($FileName))return false;
        $this->renderTreeFromInner(file_get_contents($FileName));
    }
    
    function renderTreeFromInner($_Inner){
        
        $this->ParserResource = xml_parser_create ();
        xml_parser_set_option($this->ParserResource, XML_OPTION_CASE_FOLDING, false);
        xml_set_object($this->ParserResource, $this);
        xml_set_element_handler($this->ParserResource, "_tagOpen", "_tagClosed");
        
        xml_set_character_data_handler($this->ParserResource, "_tagData");
        
        $_Inner = xml_parse($this->ParserResource,$_Inner );
        if(!$_Inner) {
            PEAR::raiseError(sprintf("XML error: %s at line %d",
                xml_error_string(xml_get_error_code($this->ParserResource)),
                xml_get_current_line_number($this->ParserResource)));
        }
              
        xml_parser_free($this->ParserResource);
    }
    
    function _tagOpen($parser, $name, $attrs){
        
        if(!isset($this->parsingNode)){
            
            $this->parsingNode = &$this;
            $this->Name = $name;
            $this->Attributes = $attrs;
        }else {
            
            $_tParent = &$this->parsingNode;
            $this->parsingNode = &$_tParent->createChildNode($name, $attrs);
        }
    }
    
    function _tagData($parser, $tagData){
        
        if(trim($tagData)||$this->parsingNode->Data){
            
            $this->parsingNode->Data .= $tagData;
        }
    }
    
    function _tagClosed($parser, $name){
        
        if(!$this->parsingNode->getParentNode())
            unset($this->parsingNode);
        else
            $this->parsingNode = &$this->parsingNode->getParentNode();
    }
    function getChildrenByName($_Name){
        
        $_TC = count($this->ChildNodes);
        $Nodes = array();
        for ( $j = 0; $j<$_TC; $j++){
            
            if(!is_a($this->ChildNodes[$j],'xmlnodex'))continue;
            if ($this->ChildNodes[$j]->getName() == $_Name){
                
                $Nodes[] = &$this->ChildNodes[$j];
            }
        }
        
        return $Nodes;
    }
    
    function getChildData($_ChildName){
        
        $children = $this->getChildrenByName($_ChildName);
        foreach($children as $_child){
            
            return $_child->getData();
        }
        return '';
    }
    /**
     * Enter description here...
     *
     * @param string $ChildName
     * @return xmlNodeX
     */
    function &getFirstChildByName($ChildName){
        
        $r_Children = $this->getChildrenByName($ChildName);
        if(!count($r_Children)){
            $r_Children = null;
            return $r_Children;
        }
        
        return $r_Children[0];
    }
    
    /**
     * Now only /xxx/xxxx/xxxxx
     *
     * @param unknown_type $_xPath
     * @return array
     */
    function xPath($_xPath){
        
        $TagNames = explode('/', $_xPath);
        $_TagName = '';
        $Nodes = array();
        while (count($TagNames)){
            
            $_TagName = array_shift($TagNames);
            if(!$_TagName)continue;
            $Ignore = false;
            if(preg_match('/[(.*?)]/', $_TagName, $SubPatterns)){
            
                $_TagName = preg_replace('/[.*?]/', '', $_TagName);
                $r_tAttributes = explode(',', $SubPatterns[1]);
                foreach ($r_tAttributes as $_Attribite){
                    
                    $_Attribite = explode('=', $_Attribite);
                    $AttributeName = preg_replace('/^@/','', $_Attribite[0]);
                    $AttributeValue = preg_replace('/^"(.*?)"$/','$1', $_Attribite[1]);
                    $n_atr = $this->getAttribute($AttributeName);
                    
                    if(!( $n_atr == $AttributeValue | '"'.$n_atr.'"' == $AttributeValue | '''.$n_atr.''' == $AttributeValue)){
                        
                        $Ignore = true;
                        break;
                    }
                }
            }
            
            if(!count($TagNames) && $_TagName==$this->getName() && !$Ignore){
                $r_t = array(&$this);
                return $r_t;
            }
            list($chTagName) = $TagNames;
            $r_Attributes = array();
            if(preg_match('/[(.*?)]/', $chTagName, $SubPatterns)){
                
                $chTagName = preg_replace('/[.*?]/', '', $chTagName);
                $r_tAttributes = explode(',', $SubPatterns[1]);
                foreach ($r_tAttributes as $_Attribite){
                    
                    $_Attribite = explode('=', $_Attribite);
                    $r_Attributes[preg_replace('/^@/','', $_Attribite[0])] = preg_replace('/^"(.*?)"$/','$1', $_Attribite[1]);
                }
            }
            
            $ChildNodes = $this->getChildrenByName($chTagName);
            
            $_TC = count($ChildNodes);
            for($n = 0; $n<$_TC; $n++){
                $Ignore = false;
                foreach ($r_Attributes as $AttributeName => $AttributeValue){
                    
                    $n_atr = $ChildNodes[$n]->getAttribute($AttributeName);
                    if(!( $n_atr == $AttributeValue | '"'.$n_atr.'"' == $AttributeValue | '''.$n_atr.''' == $AttributeValue)){
                    
                        $Ignore = true;
                        break;
                    }
                }
                if($Ignore)continue;
                
                $Nodes = array_merge($Nodes, $ChildNodes[$n]->xPath('/'.implode('/', $TagNames)));
            }
            break;
        }
        
        return $Nodes;
    }
    
        
    function saveToFile($FileName, $Tabbed = false, $encoding = 'ISO-8859-1'){
        
        $fp = fopen($FileName, 'w');
        fwrite($fp, '<?xml version="1.0" encoding="'.$encoding.'"?>'."rn".$this->getNodeXML(-1, $Tabbed));
        fclose($fp);
    }
    function setData($Data){
        
        $this->Data = $Data;
    }
    /**
     * Set or get attribute
     *
     * @param string $k
     * @param string $v
     */
    function attribute($k, $v = null){
        
        if(!is_null($v)){
            
            $this->Attributes[$k] = $v;
        }
        return $this->getAttribute($k);
    }
}
?>