04 novembre 2009

XPath Parser pour PHP

Générer un arbre syntaxique pour XPath

Mon but est de transformer une expression XPath en Arbre Syntaxique. Une petite recherche sur Internet et je trouve le projet ANTLR. Celui ci propose deux grammaires pour XPath. Il existe également un générateur de code PHP. Super ! En s'intéressant un peu à ce "runtime", j'ai l'impression d'avoir trouvé une masse pour enfoncer ma pointe... J'abandonne.
Quelque requêtes infructueuses Google plus loin, je décide d'écrire mon propre bout de code :

Un package PEAR XPath_Parser

Alors autant le dire tout de suite, ce paquet n'est pas encore capable d'analyser une grammaire XPath complète. Cela viendra peut-être un jour mais pour le moment il comprend uniquement une grammaire XPath simplifiée. Voici donc sa description rapide en BNF


    <location>   ::= [ <axis> [ <position> | [ <conditions> ] * ] ] +
    <axis>       ::= [ "child::" | "/" | "attribute::" | "@" | "parent::" | "../" | "self::" | "./" | "descendant-or-self::" | "//" ] [ <char> ] +
    <position>   ::= "[" [ <integer> ] + "]"
    <conditions> ::= "[" <condition> [ <logical> <condition> ] * "]"
    <condition>  ::= <location> <operator> <value>
    <operator>   ::= [ "or" | "and" ]
    <value>      ::= [ [ <interger> ] + | [ <char> ] + ]
    <integer>    ::= '0' - '9'
    <char>       ::= 'a' - 'Z'

Simple ne veut pas dire minimum, cette grammaire est plus riche que la grammaire MicroXPath

Usage et fonctions

Dans sa version 1.0, ce paquet permet juste de transformer une chaine XPath en tableau.


$o = new XPath_Parser("/a[@b='1']/c[@b='2' and child::e='3']//d[@b='4']");
$t = $o->getArray();

Le tableau produit par l'exemple précédent ressemblera à celui ci :
            array(
                array (
                    'axis' => 'child',
                    'localName' => 'a',
                    'condition' => array(
                        array(
                            'location' => array (
                                array (
                                    'axis' => 'attribute',
                                    'localName' => 'b',
                                ),
                            ),
                            'operator' => '=',
                            'literal' => '1',
                        )
                    ),
                ),
                array (
                    'axis' => 'child',
                    'localName' => 'c',
                    'condition' => array(
                        array(
                            'location' => array (
                                array (
                                    'axis' => 'attribute',
                                    'localName' => 'b',
                                ),
                            ),
                            'operator' => '=',
                            'literal' => '2',
                        ),
                        array(
                            'location' => array (
                                array (
                                    'axis' => 'child',
                                    'localName' => 'e',
                                ),
                            ),
                            'operator' => '=',
                            'literal' => '3',
                        )
                    ),
                ),
                array (
                    'axis' => 'descendant-or-self',
                    'localName' => 'd',
                    'condition' => array(
                        array(
                            'location' => array (
                                array (
                                    'axis' => 'attribute',
                                    'localName' => 'b',
                                ),
                            ),
                            'operator' => '=',
                            'literal' => '4',
                        )
                    ),
                ),
            )

D'autres exemples sont disponibles dans le fichier des tests unitaires.

Téléchargement et code source

Le code source est disponible sur GitHub.

Ou, on peut directement l'installer avec PEAR en s'abonnant au Channel Respear :


% pear channel-discover pear.respear.net
% pear install respear/XPath_Parser

Aucun commentaire:

Publier un commentaire