Visualizzazione dei risultati da 1 a 8 su 8

Discussione: [PHP] - Parser XML

  1. #1

    [PHP] - Parser XML

    Ho bisogno di un'aiuto per capire come risolvere questa piccola rognetta visto che sono un pippa mostruosa con XML
    sto cercando di creare un menu tipo questo però dinamico grazie ad XML e template premesso che non voglio usare XSL e tantomeno voglio rinunciare alla comodità del template ho pensato di leggere il file XML così

    <?php
    error_reporting(E_ALL);

    #definisce il file XML
    $file = "../data.xml";

    $currentTag = "";
    $attributes = "";
    $countmenu = "";
    $_PAGE['menu'] = "";

    #Debug
    $menu = Array('titolo'=>'','link'=>'',);
    $page = "";


    function StartElement($parser, $tagname, $attributes){
    $_SESSION['menu']['currentTag'] = $tagname;
    $_SESSION['menu']['currentAttribs'] = $attributes;

    switch($tagname){
    case "recordset":
    break;

    case "link":
    break;

    case "menu":
    while(list($key,$value) = each($attributes)){
    ## Visualizza il nome del menu
    echo "<tr><td>$key:$value</td>\n";
    }

    break;
    }
    }

    function EndElement($parser, $tagname){

    $_SESSION['menu']['currentTag'] = $tagname;

    switch($tagname){

    case "recordeset":
    break;

    }
    }

    function OnData($parser, $data){
    switch ($_SESSION['menu']['currentTag']){

    case "nome":
    echo "<td>$data</td>";
    break;

    case "url":
    echo "<td>$data</td>";
    break;

    }
    }

    $xml_parser = xml_parser_create(); #Inizializzazione nuovo parser XML
    xml_parser_set_option($xml_parser,XML_OPTION_CASE_ FOLDING,false);
    # callback function
    xml_set_element_handler($xml_parser, "StartElement", "EndElement");
    xml_set_character_data_handler($xml_parser, "OnData");

    # open XML file
    if (!($fp = fopen($file,"r"))) die("Impossibile aprire il tracciato XML del file $file ");

    #Lettura file XML
    while ($data = fread($fp,4096)){
    if (!xml_parse($xml_parser,$data, feof($fp)));
    }

    xml_parser_free($xml_parser);
    ?>

    l'XML è

    <?xml version="1.0" ?>
    <recordset>
    <menu name="newsletter">
    <link>
    <nome>Link newsletter1</nome>
    <url>#</url>
    </link>
    <link>
    <nome>Link newsletter2</nome>
    <url>#</url>
    </link>
    <link>
    <nome>Link newsletter3</nome>
    <url>#</url>
    </link>
    </menu>
    <menu name="news">
    <link>
    <nome>Link news1</nome>
    <url>#</url>
    </link>
    <link>
    <nome>Link news2</nome>
    <url>#</url>
    </link>
    </menu>
    </recordset>
    il risultato dello script con le echo è questo

    name:newsletter Link newsletter1 # Link newsletter2 # Link newsletter3 #
    ok..fin qui tutto bene

    1° Quesito
    solo che io vorrei in elaborazione dello script unire i nodi <nome> e <link> ed avere un output del tipo

    ho provato in tutte le maniere con sessioni, variabili globali a farlo solo che non riesco a aggirare il problema

    avete quelche coniglio ??
    Soluzioni di Web marketing, CMS, Temi wordpress, grafica e molto altro

    -----
    Ogni topic aperto con un titolo errato fa perdere un capello al moderatore che lo dovrà sistemare.. se non vuoi contribuire alla calvizia dei moderatori apri 3D a norma di regolamento, e prima fai una ricerca! No pvt tecnici!

  2. #2
    Prova questo:
    Codice PHP:
        <?php
    $indice 
    256;
    $contatore 0;
    $apri_xml fopen("data.xml"'r');

    while(!
    feof($apri_xml))
    {
        
    $buffer ltrim(Chop(fgets($apri_xml$indice)));
        if (
    $buffer == "<link>")
        {
        
    $nome ltrim(Chop(fgets($apri_xml$indice)));
        
    $url ltrim(Chop(fgets($apri_xml$indice)));

        
    $nome ereg_replace("<nome>"""$nome);
        
    $nome ereg_replace("</nome>"""$nome);

            
    $url ereg_replace("<url>"""$url);
            
    $url ereg_replace("</url>"""$url);


            echo(
    "[url=".$url."]".$nome."[/url]");
    $contatore++;
        }
    }

    fclose($apri_xml);
    ?>
    Però stai attento:
    al posto di <menu name="newsletter">...</menu> devi usare <newsletter>...</newsletter>.

    Ti consiglio poi di dividere il file xml in due dove da una parte inserisci il menu newsletter e nell'altro il menu news; in questo modo puoi aprire due file diversi e crearti due menu diversi, altrimenti tale script ti inserisci i due menu assieme.

    Tutto chiaro?

  3. #3
    Originariamente inviato da smal
    Prova questo:
    Codice PHP:
        <?php
    $indice 
    256;
    $contatore 0;
    $apri_xml fopen("data.xml"'r');

    while(!
    feof($apri_xml))
    {
        
    $buffer ltrim(Chop(fgets($apri_xml$indice)));
        if (
    $buffer == "<link>")
        {
        
    $nome ltrim(Chop(fgets($apri_xml$indice)));
        
    $url ltrim(Chop(fgets($apri_xml$indice)));

        
    $nome ereg_replace("<nome>"""$nome);
        
    $nome ereg_replace("</nome>"""$nome);

            
    $url ereg_replace("<url>"""$url);
            
    $url ereg_replace("</url>"""$url);


            echo(
    "[url=".$url."]".$nome."[/url]");
    $contatore++;
        }
    }

    fclose($apri_xml);
    ?>
    Però stai attento:
    al posto di <menu name="newsletter">...</menu> devi usare <newsletter>...</newsletter>.

    Ti consiglio poi di dividere il file xml in due dove da una parte inserisci il menu newsletter e nell'altro il menu news; in questo modo puoi aprire due file diversi e crearti due menu diversi, altrimenti tale script ti inserisci i due menu assieme.

    Tutto chiaro?
    si è tutto chiaro avevo già visto questa soluzione a livello di prestazioni rischi di appesantire un sacco la pagina e pensavo di usare una struttura piu' flessibile e un pò piu' performante..
    vediamo cosa riesco a tirare fuori dal cilindro

    cmq grazie
    Soluzioni di Web marketing, CMS, Temi wordpress, grafica e molto altro

    -----
    Ogni topic aperto con un titolo errato fa perdere un capello al moderatore che lo dovrà sistemare.. se non vuoi contribuire alla calvizia dei moderatori apri 3D a norma di regolamento, e prima fai una ricerca! No pvt tecnici!

  4. #4
    Originariamente inviato da smal
    Prova questo:
    Codice PHP:
        <?php
    $indice 
    256;
    $contatore 0;
    $apri_xml fopen("data.xml"'r');

    while(!
    feof($apri_xml))
    {
        
    $buffer ltrim(Chop(fgets($apri_xml$indice)));
        if (
    $buffer == "<link>")
        {
        
    $nome ltrim(Chop(fgets($apri_xml$indice)));
        
    $url ltrim(Chop(fgets($apri_xml$indice)));

        
    $nome ereg_replace("<nome>"""$nome);
        
    $nome ereg_replace("</nome>"""$nome);

            
    $url ereg_replace("<url>"""$url);
            
    $url ereg_replace("</url>"""$url);


            echo(
    "[url=".$url."]".$nome."[/url]");
    $contatore++;
        }
    }

    fclose($apri_xml);
    ?>
    Però stai attento:
    al posto di <menu name="newsletter">...</menu> devi usare <newsletter>...</newsletter>.

    Ti consiglio poi di dividere il file xml in due dove da una parte inserisci il menu newsletter e nell'altro il menu news; in questo modo puoi aprire due file diversi e crearti due menu diversi, altrimenti tale script ti inserisci i due menu assieme.

    Tutto chiaro?
    confrontando i 2 metodi teoricamente il tuo dovrebbe essere quello piu' lento

    e invece ..

    0.00296497344971 con un certo numero di eregi
    0.00727701187134 con il mio metodo senza eregi con però n ricorsioni nel file

    mi sa che ora proverò a mettere mano per trasformarlo secondo le mie esigenze
    Soluzioni di Web marketing, CMS, Temi wordpress, grafica e molto altro

    -----
    Ogni topic aperto con un titolo errato fa perdere un capello al moderatore che lo dovrà sistemare.. se non vuoi contribuire alla calvizia dei moderatori apri 3D a norma di regolamento, e prima fai una ricerca! No pvt tecnici!

  5. #5
    Sicuramente di questi tempi io sono rinco^2... (non ringo) ma se ho ben capito tu vuoi costruire un link... se la montagna non va a maometto, maometto va alla montagna...

    inverti le posizioni nel file xml in questo modo:

    codice:
    <?xml version="1.0"  ?>
        <recordset>
        <menu name="newsletter">
        <link>
        <url>#</url>
        <nome>Link newsletter1</nome>
        </link>
        <link>
        <url>#</url>
        <nome>Link newsletter2</nome>
        </link>
        <link>
        <url>#</url>
        <nome>Link newsletter3</nome>
        </link>
        </menu>
    ....
    ....
    ....
        </recordset>
    Poi nella funzione:
    codice:
    function OnData($parser, $data){
    
    switch ($_SESSION['menu']['currentTag']){
    
    case "url":
    echo "<td><a href=\"$data\">";
    break;
    
    case "nome":
    echo "$data</a></td>";
    break;
    
    }
    }
    ripeto che il caldo e la guinness fanno primati (nel senso delle scimmie) ma mi pare che possa risolvere il tuo problema.


    Il silenzio è spesso la cosa migliore. Pensa ... è gratis.

  6. #6
    ma xche usare strani sistemi quando ci sono i comodissimi parser xml?

    rinco personalmente mi trovo meglio con
    http://it2.php.net/manual/it/ref.dom.php

    che è un parser XML w3c compliant (se hai usato il parser w3c compliant di un altro linguaggio i metodi/proprietà/costanti/ecceccecc sono identici)

    se non lo hai fatto ...

    codice:
    <?php
    $menuData = array();
    $menuID = 0;
    $menuLinkID = 0;
    
    $menuXmlDocument = new DOMDocument();
    $menuXmlDocument->load("menu.xml");
    
    // Cicla i nodi di recordset
    $mxdMenuNode = $menuXmlDocument->firstChild->firstChild;
    while(!is_null($mxdMenuNode))
    {
        switch ($mxdMenuNode->nodeType)
        {
            case XML_ELEMENT_NODE:
                
                $menuData[] = array();
                $menuID = count($menuData) - 1;
                
                $menuLinkID = 0;
                
                // Cicla l'elenco dei link
                $mxdMenuSubNodes = $mxdMenuNode->firstChild;
                while(!is_null($mxdMenuSubNodes))
                {
                    switch ($mxdMenuSubNodes->nodeType)
                    {
                        case XML_ELEMENT_NODE:
                            
                            switch ($mxdMenuSubNodes->nodeName)
                            {
                                case 'name':
                                    
                                    // Imposta il nome del menu nell'array
                                    $menuData[$menuID]['name'] = $mxdMenuSubNodes->nodeValue;
                                    break;
                                    
                                case 'link':
                                    
                                    // Acquisisce le informazioni sul link
                                    if (!isset($menuData[$menuID]['links']))
                                    {
                                        $menuData[$menuID]['links'] = array();
                                    }
                                    
                                    // Inizializza il container delle informazioni del link e
                                    // salva l'id dell'elemento appena creato
                                    $menuData[$menuID]['links'][] = array('name' => '', 'url' => '');
                                    $menuLinkID = count($menuData[$menuID]['links']) - 1;
                                    
                                    // Cicla i sotto nodi dell'elemento link per estrarre le proprietà 
                                    // del link stesso
                                    $mxdLinkSubNodes = $mxdMenuSubNodes->firstChild;
                                    while(!is_null($mxdLinkSubNodes))
                                    {
                                        switch ($mxdLinkSubNodes->nodeType)
                                        {
                                            case XML_ELEMENT_NODE:
                                                
                                                switch ($mxdLinkSubNodes->nodeName)
                                                {
                                                    case 'name':
                                                        
                                                        $menuData[$menuID]['links'][$menuLinkID]['name'] = $mxdLinkSubNodes->nodeValue;
                                                        break;
                                                        
                                                    case 'url':
                                                        
                                                        $menuData[$menuID]['links'][$menuLinkID]['url'] = $mxdLinkSubNodes->nodeValue;
                                                        break;
                                                }
                                                
                                                break;
                                        }
                                        
                                        $mxdLinkSubNodes = $mxdLinkSubNodes->nextSibling;
                                    }
                                    
                                    break;
                            }
                            
                            break;
                            
                    }
                    
                    $mxdMenuSubNodes = $mxdMenuSubNodes->nextSibling;
            }
        }
        
        $mxdMenuNode = $mxdMenuNode->nextSibling;
    }
    
    echo "<pre>";
    print_r($menuData);
    
    ?>
    questo codice ti riporta il un file XML (simile a quello tuo) sotto forma di array ... l'input è

    codice:
    <?xml version="1.0" ?>
    <recordset>
        
        <menu>
            
            <name>NewsLetter</name>
            
            <link>
                <name>Link newsletter1</name>
                <url>#</url>
            </link>
            
            <link>
                <name>Link newsletter2</name>
                <url>#</url>
            </link>
            
            <link>
                <name>Link newsletter3</name>
                <url>#</url>
            </link>
            
        </menu>
        
        <menu>
            
            <name>News</name>
            
            <link>
                <name>Link news1</name>
                <url>#</url>
            </link>
            
            <link>
                <name>Link news2</name>
                <url>#</url>
            </link>
            
        </menu>
        
    </recordset>
    l'output
    codice:
    Array
    (
        [0] => Array
            (
                [name] => NewsLetter
                [links] => Array
                    (
                        [0] => Array
                            (
                                [name] => Link newsletter1
                                [url] => #
                            )
    
                        [1] => Array
                            (
                                [name] => Link newsletter2
                                [url] => #
                            )
    
                        [2] => Array
                            (
                                [name] => Link newsletter3
                                [url] => #
                            )
    
                    )
    
            )
    
        [1] => Array
            (
                [name] => News
                [links] => Array
                    (
                        [0] => Array
                            (
                                [name] => Link news1
                                [url] => #
                            )
    
                        [1] => Array
                            (
                                [name] => Link news2
                                [url] => #
                            )
    
                    )
    
            )
    
    )
    il codice può sembrare mastodondico ... ma in compenso:
    - dove vai vai ... se c'è un parser W3C compliant ... vai tranquillo (al MAX cambia la nomenclatura, ovvero la forma delle proprietà e dei metodi (invece di essere childNodes sarà child_nodes))
    - ti da la flessibilità che l'xml ti permette ... ad aggiungere un qualsiasi supporto aggiuntivo da qualche parte hai bisogno di pochissimissime righe di codice ^^
    E se vuoi cambiare il formato del file, una volta scritto il codice la prima volta, si tratta solo di spostare il codice che fa l'estrazione e di cambiare il nome dei nodi ... infatti le operazioni sono sempre uguali ... mentre altri sistemi che non implicano l'uso di un parser XML ti complicherebberò infinitamente la vita (dovresti buttare tutto il codice o quasi [dipende dall'entità della modifica al codice xml] e riscriverlo)


    per gestire anche la ricorsione (ovvero menu di sotto menu di sotto menu) è da cambiare un po xche x evitare la ricorsione deve usare un'array che contenga array di nodi, in modo mettere tutto in lista. L'array deve avere una struttura tale da contenere sia l'elenco di nodi sia il nodo che li contiene, ma per questa seconda cosa si dovrebbe poter usare la proprietà parentNode e si dovrebbe risolvere il problema abb. velocemente.
    Per agganciare le due cose in un array personalmente ti consiglio o di usare un HASH dell'oggetto nodo padre.
    Tra quello che mi hai detto stamani e quello che leggo adesso non ho molto chiaro quello che devi fare (mi avevi parlato di ricorsione ma ricorsione nel file xml non ne ho visto)

    cmq ti consiglio di "srotolare" i loop ricorsivi xche si macinano la macchina soprattutto per lo stack e la memoria usata. Per i tempi di esecuzione non so se cambia qualcosa e se si quanto cambia anche se in realtà non ci dovrebbe essere tantissima differenza (ma a livello di performance solamente)

  7. #7
    Spero che il mio non sembra un rimprovero o chissà che cosa, ma vorrei solo dirti che io ho provato a visitare php.net quando cercavo un parser xml che sfruttava il DOM, ma non avevo trovato niente che per me era comprensibile. Poi per quanto riguardava parserizzare un XML sfruttando il DOM tramite il php, non ne parla neanche freephp.
    Quindi mi sono arrangiato da me e da qualche parte ho trovato questo parser. E a dire il vero un parser strapieno di switch per me non è semplice da scrivere.

    Quindi non ti meravigliare se adottiamo soluzioni "strane" o pesanti.

  8. #8
    non si tratta di soluzioni "strane" o "pesanti" ma si tratta di utilizzare la tecnologia corretta o meno

    nel senso che se già c'è la ruota non serve reinventarla.

    non so quando tu abbia guardato sul manuale di php ma un parser xml quasi w3c compliant ci sta da parecchio, da prima della ver 4.3.0 di php

    Nella versione 4.3.0 di PHP l'estensione DOM XML è stata rivista in modo da fornire una migliore adesione allo standard DOM. Il modulo contiene ancora diverse vecchie funzioni, ma non dovrebbero essere più usate. Specialmente quelle funzioni non orientate agli oggetti.
    e per quanto riguarda la comprendibilità ... guarda quello non è un problema ne un limite ... infatti si tratta solo di capire bene come lavora
    Se ti cambia la struttura del file XML e diventa tutta su rigo devi cambiare il codice, con il parser xml no ... se spuntano dei dati in + nel file ... in base a come hai fatto il codice ciò può dare seri problemi o meno ... se vuoi aggiungere nuove categorie o subcatogorie o la ricorsività ... col parser lo fai in poco ... tramite altri sistemi non so nemmeno se è fattibile e comunque se lo è lo si potrà fare tramite arzigogolati sistemi.

    personalmente ti consiglio di dare un occhio al parser per due motivi:
    1° se hai necessità di usare xml in altri linguaggi e questi implementano un parser xml w3c compliant, con poca fativa puoi fare quello che ti serve

    2° hai una maggiore flessibilità

    ))

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.