Buscando nun XML con XPath

PHP No Comments »

SimpleXMLElement tamén permite facer busquedas dentro dun XML empregando XPath, unha linguaxe de recorrido de XML. Para elo dispoñemos do método SimpleXMLElement->xpath(ruta), que devolve un array cos elementos atopados. A ruta indica que elementos estamos a buscar, e segue a sintase da linguaxe XPath.

Un tutorial bastante sinxelo de iniciación a XPath, que nos pode axudar a entender como buscar dentro do XML empregando esta linguaxe: http://sherekan.com.ar/2008/09/16/introduccion-a-xpath/

$libraria = new SimpleXMLElement('ficheiro.xml',NULL,true);

// Obter todos os nodos editor
$listado = $libraria->xpath('//editor');
foreach($listado as $ele)
	echo $ele ."<br />";

// Obter od nodos editor situados dentro dun nodo libro situado
// a sua vez no nodo raíz libraria
$listado = $libraria->xpath('/libraria/libro/editor');
foreach($listado as $ele)
	echo $ele ."<br />";

// Obter todos os atributos isbn
$listado = $libraria->xpath('//@isbn');
foreach($listado as $ele)
	echo $ele ."<br />";

Como engadir un nodo a un XML

PHP No Comments »

Seguindo co uso da clase SimpleXML (http://es.php.net/manual/es/book.simplexml.php) tamén se pode engadir de xeito sinxelo un novo nodo a un XML. Para isto temos que crear un obxeto da clase SimpleXMLElement, inicializándoo ben cun String que conteña o XML (new SimpleXMLElement(string) ) ou ben co nome do ficheiro que conteña o XML ( new SimpleXMLElement(ficheiro,NULL,True) ). Tamén dispoñemos de dúas funcións que obteñen o mesmo obxeto (simplexml_load_string(string) e simplexml_load_file(ficheiroXML)).

Unha vez obtido o obxeto SimpleXMLElement, podemos acceder o nome de cada nodo, os seus atributos e os seus sobnodos cos métodos do obxeto (e con estes métodos situarnos no nodo onde queremos engadir o novo subnodo):

  • SimpleXMLElement->getName() para obter o nome do nodo
  • SimpleXMLElement->attributes() para obter un array cos atributos do nodo
  • SimpleXMLElement->children() para obter un array cos subnodos dun nodo dado
  • E engadir un novo nodo unha vez que estemos situado no punto axeitado do XML:

  • SimpleXMLElement->addChild(nome_nodo,valor_nodo) : Engade un novo nodo no punto indicado. Dito nodo terá unha etiqueta cuxo nome será o indicado no primeiro parámetro e se se indica segundo parámetro, ese será o valor do nodo.
  • SimpleXMLElement->addAttribute(nome_atributo,valor_atributo) : Engadelle o nodo actual un atributo co nome indicado no primeiro parámetro e o valor indicado no segundo.
  • Un exemplo de como engadir un nodo a un ficheiro XML e velo no navegador:

    $libraria = new SimpleXMLElement('ficheiro.xml',NULL,true);
    
    $novo_nodo = $libraria->addChild("libro");
    $novo_nodo->addAttribute('isbn','0812550706');
    $novo_nodo->addChild('titulo','Novo libro');
    $novo_nodo->addChild('autor','Novo autor');
    $novo_nodo->addChild('editor','Novo editor');
    
    echo $novo_nodo->asXML();
    

    Como percorrer un XML

    PHP No Comments »

    Facendo uso da clase SimpleXML (http://es.php.net/manual/es/book.simplexml.php) pódese percorrer de forma sinxela un XML. Para isto temos que crear un obxeto da clase SimpleXMLElement, inicializándoo ben cun String que conteña o XML (new SimpleXMLElement(string) ) ou ben co nome do ficheiro que conteña o XML ( new SimpleXMLElement(ficheiro,NULL,True) ). Tamén dispoñemos de dúas funcións que obteñen o mesmo obxeto (simplexml_load_string(string) e simplexml_load_file(ficheiroXML)).

    Unha vez obtido o obxeto SimpleXMLElement, podemos acceder o nome de cada nodo, os seus atributos e os seus sobnodos cos métodos do obxeto:

  • SimpleXMLElement->getName() para obter o nome do nodo
  • SimpleXMLElement->attributes() para obter un array cos atributos do nodo
  • SimpleXMLElement->children() para obter un array cos subnodos dun nodo dado
  • Se temos o seguinte XML:

    <?xml version="1.0" ?>
    <libraria>
    	<libro isbn="0345342968">
    		<titulo>Fahrenheit 451</titulo>
    		<autor>R. Brandbury</autor>
    		<editor>Del Rey</editor>
    	</libro>
    	<libro isbn="0048231398">
    		<titulo>The Silmarillion</titulo>
    		<autor>J.R.R. Tolkien</autor>
    		<editor>G. Allen and Unwin</editor>
    	</libro>
    	<libro isbn="0451524934">
    		<titulo>1984</titulo>
    		<autor>G. Orwell</autor>
    		<editor>Signet</editor>
    	</libro>
    	<libro isbn="031219126X">
    		<titulo>Frankenstein</titulo>
    		<autor>M. Shelley</autor>
    		<editor>Bedford</editor>
    	</libro>
    	<libro isbn="0312863551">
    		<titulo>The Moon Is a Harsh Mistress</titulo>
    		<autor>R. A. Heinlein</autor>
    		<editor>Orb</editor>
    	</libro>
    </libraria>
    

    Podemos percorrelo facendo uso dos obxetos e métodos vistos anteriormente:

    $libraria = new SimpleXMLElement('ficheiro.xml',NULL,true);
    procesar_Nodo($libraria);
    
    function procesar_Nodo($nodo) {
    	echo "<b>NODO :</b>".$nodo->getName() . "<br />";
    	// SE TEN ATRIBUTOS
    
    	if (count($nodo->attributes()) > 0) {
    		echo "<b>atributos :</b><br />";
    		foreach ($nodo->attributes() as $atributo) {
    			echo "  --<b>".$atributo->getName() ."</b>: ". $atributo . "<br />";
    		}
    	}
    
    	// SE NON TEN FILLOS IMPRIMESE O CONTIDO
    	if (count($nodo->children()) == 0) {
    		echo $nodo . "<br />";
    	}
    	foreach($nodo->children() as $subnodo) {
    		procesar_Nodo($subnodo);
    	}
    }
    

    O patrón Registry (rexistro)

    PHP No Comments »

    Ao emprego do patrón Registry ven a solucionar o problema de ter que pasar a obxetos ou funcións da nosa aplicación unha chea de parámetros ou ter que empregar variables globais. Consiste en crear un obxeto que conten un array asociativo onde se van gardando os valores que se desexe xunto co seu nome, de forma que serán accesibles posteriormente con so coñecer o nome da variable á que se desexa acceder.

    Asi en lugares de pasarlle as función, métodos ou constructores de obxetos unha chea de parámetros, pasaselle só un, o obxeto Registry.

    class patronRegistry {
        private static $_cache = array();
    
        public static function set($indice, &$valor) {
            self::$_cache[$indice] = $valor;
        }
        public static function &get($indice) {
            return self::$_cache[$indice];
        }
        public static function existe($indice) {
            return (self::get($indice) !== null);
        }
    }
    
    $obxeto1 = accesoDB::getAcceso();
    patronRegistry::set("accesoDB",$obxeto1);
    var_dump($obxeto1->getIdConexion());
    $obxeto2 = accesoDB::getAcceso();
    var_dump($obxeto2->getIdConexion());
    if (patronRegistry::existe("accesoDB")) {
      $obxeto3 = patronRegistry::get("accesoDB");
      var_dump($obxeto3->getIdConexion());
    }
    

    O patrón Singleton (instancia única)

    PHP No Comments »

    Os patróns de programación son técnicas ben coñecidas e probadas para resolver determinados problemas de programación.

    Un dos patróns é o Patrón Singletón que serve para acceder a recursos (ficheiros, conexións a base de datos) onde so se pode crear unha única instancia dese acceso (so unha conexión a BD, …). Para evitar que se creen varios accesos a dito recurso empregase as técnicas índicadas neste patrón..

    As técnicas que recolle este patrón para resolver dito problema son:

  • A visibiliade do constructor é privada, co que non é instanciable esta clase directamente, e así evitase que se vain creando varios accesos ao recurso (varias instancias do obxeto de acceso ao recurso)
  • Dispón dun método público e estático (método de clase) para obter o acceso ao recurso, método ao que se chamará cada vez que se quere obter un acceso a ese recurso
  • Dentro dese método, e empregando unha propiedade estática (de clase), comprobarase se xa se creou unha instancia do obxeto de acceso (que estará gardada se así foi nesa propiedade estática). Se non se creou, crease e gardase nesa propiedade; e en calquera caso devolvese o gardado nese propiedad (é dicir, se non se creou un obxeto de acceso, crease, e se non devolvese o existente, co que se evita crear varias instancias)
  • A súa implementación en PHP5 é a seguinte:

    class PatronSingleton
    {
        // Contenedor Instancia da Clase
        private static $instancia;
    
        // O constructor non é accesible
        private function __construct()
        {
            echo 'Son o constructor';
        }
    
        // O metodo accesible
        public static function singleton()
        {
            if (!isset(self::$instancia)) {
                $c = __CLASS__;
                self::$instancia = new $c;
            }
            return self::$instancia;
        }
    }
    
    $obxeto1 = PatronSingleton::singleton();
    $obxeto2 = PatronSingleton::singleton();
    

    Por exemplo, para realizar a conexión a un servidor de BD MySQL empregando este patrón de diseño:

    class accesoDB
    {
        // Contenedor Instancia da Clase
        private static $instancia;
        private $id_conexion;	
    
        // O constructor non é accesible
        private function __construct()
        {
            $this->id_conexion = mysql_connect("localhost","usuario","contrasinal");
        }
    
        // O metodo accesible
        public static function getAcceso()
        {
            if (!isset(self::$instancia)) {
                $c = __CLASS__;
                self::$instancia = new $c;
            }
    
            return self::$instancia;
        }
    
        public function getIdConexion() {
            return $this->id_conexion;
        }
    }
    
    $obxeto1 = accesoDB::getAcceso();
    var_dump($obxeto1->getIdConexion());
    $obxeto2 = accesoDB::getAcceso();
    var_dump($obxeto2->getIdConexion());
    

    Como se pode ver, devolvese sempre o mesmo identificador de recurso de conexión a BD, independentemente das veces que se emprege.

    POO: Olvideime de incluir unha clase, autocarga

    PHP No Comments »

    Antes de empregar unha clase (para instanciar un obxeto), a clase ten que estar definida. Como o habitual e ter cada clase nun arquivo, é necesario antes de instanciar o obxeto incluir o fichero coa definición da clase. Se hai moitas clases, isto pode ser un pouco lioso.

    Un truco consisten en gardar cada clase nun ficheiro que teña por nome, o nome da clase e extensión PHP (a clase unhaClase podémola gardar no ficheiro unhaClase.php). PHP5 cando necesita empregar unha clase e non a atopa definida, dase unha segunda oportunidade e chama a función __autoload(). Se a función esta definida, execútase, e nela temos que ser quen de cargar o arquivo coa clase que se necesita. Podese facer algo así:

    function __autoload($nome_da_clase) {
        require_once($nome_da_clase . '.php');
    }
    
    $obx1  = new claseUnha();
    $obx2 = new claseDuas();
    

    POO: E ti de quen vés sendo

    PHP No Comments »

    Hay unha serie de funcións que permiten obter información de obxetos e clases:

  • method_exists(obxeto,metodo)
  • property_exists(clase,propiedade)
  • class_exists(clase)
  • interface_exists(interface)
  • get_class_vars(clase)
  • get_class_methods(clase)
  • get_object_vars(obxeto)
  • get_class(obxeto)
  • get_parent_class(clase ou obxeto)
  • obxeto instanceof clase
    $obxeto1 = new clasePai();
    $obxeto2 = new clasePai();
    
    var_dump($obxeto1 instanceof claseNai); // Falso
    var_dump($obxeto1 instanceof clasePai); // Verdadeiro
    

    É importante ter en conta como funcionan os operadores de igualdade e identidade cos obxetos:

  • Dous obxetos son iguais == se son instancias da mesma clase e teñen as mesmas propiedades e valores
  • Dous obxetos son identicos === se son a mesma instancia dunha clase
  • $obxeto1 = new clasePai();
    $obxeto2 = new clasePai();
    
    var_dump($obxeto1 == $obxeto2); // E verdadeiro, son da mesma clase e cos mesmos valores nas propiedades
    var_dump($obxeto1 === $obxeto2); // E falso, son instancias distintas
    

    POO: Quero desherdar a todo o mundo

    PHP No Comments »

    Se queremos que dunha clase non poda herdar ningunha clase filla, a solución consiste en empregar a palabra reservada final a esquerda da palabra class na definición da clase ( final class nome_da_clase).

    final class clasePai
    {
        public static $publica = 'Publica';
        protected static $protexida = 'Protexida';
        private static $privada = 'Privada';
    }
    
    class claseFilla extends clasePai
    {
      // Produce un fatal error - non se pode herdar dunha clase final
    }
    

    Se queremos que dunha clase si podan herdar clases fillas, pero non podan reescribir os métodos (volver a escribir un código distinto para un método xa definido na clase pai), tamén podemos aplicar o modificador final a definición do método poñendo a palabra final diante da definición do método (final function nome_metodo() ).

    class clasePai
    {
        public static $publica = 'Publica';
        protected static $protexida = 'Protexida';
        private static $privada = 'Privada';
    
        final function metodoFinal () {
        }
    }
    
    class claseFilla extends clasePai
    {
       function metodoFinal () {
       // Produce un fatal error - non se pode reescribir un método final
       }
    }
    

    POO: Unha clase sen código = un interface

    PHP No Comments »

    En PHP tamén se poden crear clases que non teñan propiedades e con todos os métodos sen código. Estas clases especiais chámanse interfaces.

    Nun interface, ningún dos métodos definidos ten código, so se define o seu nome, a súa visibilidade e os seus parámetros. A utilidade dos interfaces, é indicarlle ao programador cales son os métodos que debe implementar nas súas clases, que nome, visibilidade e parámetros teñen ditos métodos.

    Un interface defínese como unha clase normal pero sustituindo a palabra class pola palabra reservada interface.

    interface claseMoiAbstracta
    {
        function metodoBaleiro();
        function metodoSenDefinir($parametro1);
    }
    

    Para empregar un interface nunha clase empregase a palabra reservada implements despois do nome da clase filla e antes do nome do interface (ou dunha lista de interfaces separados por comas).

    class claseFilla implements claseMoiAbstracta
    {
        public function metodoBaleiro() {
        }
        public function metodoSenDefinir($parametro1) {
        }
    }
    
    $obxeto2 = new claseFilla();
    

    Hai que ter en conta:

  • Unha clase pode implementar cantos interfaces desexe (implements), pero so herdar dunha clase pai (extends)
  • Nos métodos do interface non se pon visibilidade (ou si se pon é publica)
  • Os método do interface redefinidos na clase filla teñen que ter visibilidade pública

  • Deseñado por Norick - WPMU Theme pack by WPMU-DEV.
    Entries RSS Comments RSS Iniciar sesión