<?php

class XMLStruct
{
    
    private $xml_fl;
    // flux xml
    private $current_node;
    
    private $xpath;
    
    private $dom;
    
    private $ns;
    
    /**
     *
     * Construit un objet de gestion de flux de données
     * sous forme d'XML
     *
     *
     * @param string $nfl
     *            Flux XML
     */
    function __construct($nfl = null)
    {
        $this->dom = new DOMDocument('1.0', 'UTF-8');
        $this->dom->preserveWhiteSpace = true;
        $this->dom->substitueEntities = false;
        
        if ($nfl) {
            if (is_file($nfl))
                $this->dom->load($nfl);
                else
                    $this->dom->loadXML($nfl);
                    
                    $this->xml_fl = & $nfl;
        }
        
        $this->xpath = new DOMXPath($this->dom);
    }
    
    function cd($path)
    {
        $sub = substr($path, 0, 2);
        
        switch ($sub) {
            case '//':
                $this->current_node = $path;
                break;
                
            case './':
                $path = substr($path, 1);
                $this->current_node .= $path;
                break;
            case '..':
                $pathArr = explode('/', $this->current_node);
                $nPathArr = explode('/', $path);
                while ($nPathArr[0] == '..') {
                    array_pop($pathArr);
                    array_shift($nPathArr);
                }
                $this->current_node = implode('/', $pathArr);
                break;
            default:
                $this->current_node .= '/' . $path;
                break;
        }
    }
    
    function getNodes($node = '')
    {
        if (! empty($this->current_node) && ! empty($node))
            $node = $this->current_node . '/' . $node;
            else if (empty($node))
                $node = $this->current_node;
                else if (empty($this->current_node) && empty($node))
                    $node = '//*';
                    
                    return $this->xpath->query($node);
    }
    
    function toStringNode($node)
    {
        return $this->dom->saveXML($node);
    }
    
    function toString($path = '')
    {
        $nodes = $this->getNodes($path);
        
        if ($nodes->length > 0)
            return $this->dom->saveXML($nodes->item(0));
            else
                return 'Erreur : Noeud vide...';
    }
    
    function addNamespace($prefix, $uri)
    {
        $this->xpath->registerNamespace($prefix, $uri);
        $this->ns[$prefix] = $uri;
    }
    
    function output()
    {
        return $this->dom->saveXML();
    }
    
    function getPath()
    {
        return $this->current_node;
    }
    
    function input(& $nfl)
    {
        $this->xml_fl = $nfl;
        
        $this->dom->loadXML($nfl);
        
        $this->xpath = new DOMXPath($this->dom);
        
        if (is_array($this->ns))
            foreach ($this->ns as $prefix => $uri)
                $this->addNamespace($prefix, $uri);
    }
    
    function addNode($nodeParent, $name, $attributes = array(), $value = null)
    {
        // ne pas toucher a ce bout de code en effet on met en entities le flux complet et ensuite a la fin un traduction en html numérique va faire le reste
        $value = htmlspecialchars($value, ENT_QUOTES | HTML_ENTITIES | HTML_SPECIALCHARS);
        
        $elm = new DOMElement($name, ($value));
        $nodeParent->appendChild($elm);
        
        foreach ($attributes as $nAtt => & $vAtt) {
            // ne pas toucher a ce bout de code en effet on met en entities le flux complet et ensuite a la fin un traduction en html numérique va faire le reste
            $vAtt = htmlspecialchars($vAtt, ENT_QUOTES | HTML_ENTITIES | HTML_SPECIALCHARS);
            $elm->setAttribute($nAtt, $vAtt);
        }
        
        return $elm;
    }
    
    function addDOMNode($nodeParent, $elm)
    {
        $nodeParent->appendChild($elm);
        
        return $elm;
    }
    
    function createDocument($rootName, $attributes = array(), $value = null)
    {
        try {
            $elm = new DOMElement($rootName, $value);
            $this->dom = new DOMDocument('1.0', 'UTF-8');
            $this->dom->substitueEntities = false;
            $this->dom->appendChild($elm);
            
            foreach ($attributes as $nAtt => & $vAtt)
                $elm->setAttribute($nAtt, $vAtt);
                
                return $elm;
        } catch (Exception $e) {
            echo 'ici', $rootName;
            exit();
        }
    }
    
    function removeNode($nodeParent, $node)
    {
        $nodeParent->removeChild($node);
    }
    
    function save($file)
    {
        $this->dom->save($file);
    }
    
    function validate($xsd)
    {
        return $this->dom->schemaValidate($xsd);
    }
}