[PHP] XML lesen



  • Hi, ich benutze zum lesen von xml folgenden Code:

    <?
    $link_prefix    =    "· ";
    $link_postfix    =    "<BR>\n";
    
    $show_abstract        =    true;
    $ab_link_prefix    =    "";
    $ab_link_postfix    =    "<BR>\n";
    $ab_prefix            =    "";
    $ab_postfix            =    "<BR><BR>\n";
    $ab_more                =    "[mehr...]";
    $ab_more_prefix    =    " \n";
    
    $cache_file        =    "tmp.cache";
    $cache_time        =    0;
    $max_items        =    10;
    $max_readsize    =    10000;
    $target            =    "_top";
    
    //    End of customizations
    
    $backend    =    "test.xml";
    
    $items        =    0;
    $time        =    split(" ", microtime());
    
    srand((double)microtime()*1000000);
    $cache_time_rnd    =    300 - rand(0, 600);
    
    if ( (!(file_exists($cache_file))) || ((filectime($cache_file) + $cache_time - $time[1]) + $cache_time_rnd < 0) || (!(filesize($cache_file))) ) {
    
        $fpread = fopen($backend, 'r');
        if(!$fpread) {
    //        echo "$errstr ($errno)<br>\n";
    //        exit;
        } else {
    
            $fpwrite = fopen($cache_file, 'w');
            if(!$fpwrite) {
    //            echo "$errstr ($errno)<br>\n";
    //            exit;
            } else {
                $string = fread($fpread, $max_readsize);
    
                $pattern = "/<ARTIKEL>(.*?)<\/ARTIKEL>/is";
                if (preg_match_all($pattern, $string, $match, PREG_SET_ORDER))
                    for($i= 0; $i< min(count($match), $max_items); $i++){
                        $artikel= $match[$i][1];
    
                        $pattern = "/<HEADLINE>(.*?)<\/HEADLINE>/i";
                        preg_match($pattern, $artikel, $lmatch);
                        $title= $lmatch[1];
    
                        $pattern = "/<URL>(.*?)<\/URL>/i";
                        preg_match($pattern, $artikel, $lmatch);
                        $link= $lmatch[1];
    
                        if($items== 0 && $show_abstract){
                            $pattern = "/<ABSTRACT>(.*?)<\/ABSTRACT>/i";
                            preg_match($pattern, $artikel, $lmatch);
                            $abstract= $lmatch[1];
    
                            fputs($fpwrite, $ab_link_prefix."<A HREF=\"".$link."\" TARGET=\"".$target."\">".$title."</A>".$ab_link_postfix);
                            fputs($fpwrite, $ab_prefix.$abstract.$ab_more_prefix."<A HREF=\"".$link."\" TARGET=\"".$target."\">".$ab_more."</A>".$ab_postfix);
                        }else
                            fputs($fpwrite, $link_prefix."<A HREF=\"".$link."\" TARGET=\"".$target."\">".$title."</A>".$link_postfix);
    
                        $items++;
                }
            }
            fclose($fpread);
        }
        fclose($fpwrite);
    }
    if (file_exists($cache_file)) {
        include($cache_file);
    }
    ?>
    

    XML zum lesen: http://www.filesforfree.de/test.xml

    Leider funzt der aber nicht, ok, sind andere Variablen, aber auch wenn ich die in meinem script verändere gehts nicht, woran liegt das, kann mir einer helfen?



  • Hi,

    ich würde an Deiner Stelle ein XML-File grundlegend anders einlesen, schließlich bietet PHP dafür extra Funktionen.

    Ich hau Dir hier mal ein Beispiel für eine Navigation hin, ich hoffe es ist ok, wenn das n bissl länger wird jetzt.

    Das werden jetzt 3 Dateien. (test.php), (xml.class.php), und das xml-file (menu.xml).

    menu.xml

    <?xml version="1.0" standalone="yes"?>
    <!DOCTYPE menu SYSTEM "menu.dtd">
    
    <menu>
        <item name="Menu 1"></item>
        <item name="Menu 2"></item>
        <item name="Menu 3">
            <subitem>Menu 3-1</subitem>
            <subitem>Menu 3-2</subitem>
        </item>
        <item name="Menu 4">
            <subitem>Menu 4-1</subitem>
        </item>
        <item name="Menu 5">
            <subitem>Menu 5-1</subitem>
            <subitem>Menu 5-2</subitem>
            <subitem>Menu 5-3</subitem>
        </item>
        <item name="Menu 6"></item>
    </menu>
    

    xml.class.php

    <?php 
        class XML
        {
            var $parser;
            var $xml_file;
            var $html;
            var $open_tag;
            var $close_tag;
    
            function XML ( $file = null )
            {
                $this->parser = "";
                $this->html = "";
    
                if ( $file != "" )
                    $this->xml_file = $file;
    
                $this->parser = xml_parser_create ( );
    
                $this->open_tag = Array ( "menu" => "<table cellspacing='0' cellpadding='2' border='0'><tr>",
                                    "item" => "<td valign='top'><font size='3'>",
                                    "subitem" => "<br /><font size='2'>"
                                 );            
    
                $this->close_tag = Array ( "menu" => "</tr></table>",
                                    "item" => "</font></td>",
                                    "subitem" => "</font>"
                                 );            
            }
    
            function destroy ( )
            {
                xml_parser_free ( $this->parser );
            }
    
            function element_start ( $parser, $name, $attrib )
            {
                if ( count($attrib) > 0 )
                    $this->html .= $this->open_tag[$name] . $attrib['name'];
                else
                {  
                    if ( $str = $this->open_tag[$name] )
                        $this->html .= $str;
                }   
            }
    
            function element_close ( $parser, $name )
            {
                if ( $str = $this->close_tag[$name] )
                    $this->html .= $str;
            }
    
            function element_data ( $parser, $data )
            {
                $this->html .= $data;
            }        
    
            function parse ( )
            {
                xml_set_object ( $this->parser, &$this );
                xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
                xml_set_character_data_handler ( $this->parser, "element_data" );
                xml_set_element_handler ( $this->parser, "element_start", "element_close" );
    
                if (  !($fp = fopen ( $this->xml_file, "r" ))  )
                    die ( "Opening XML-File failed!\n" );
    
                while (  $data = fread ( $fp, 2048 ) )
                {
                    if ( !xml_parse ( $this->parser, $data, feof($fp) )  )
                    {
                        die(sprintf("XML error: %s at line %d",
                                        xml_error_string( xml_get_error_code($this->parser)),
                                        xml_get_current_line_number($this->parser)));
                    }
                }
            }
        }
    ?>
    

    test.php

    <?php 
        include "xml.class.php";
        $xml = new XML ( "menu.xml" );
    
        $xml->parse ( );
        echo $xml->html;
    
        $xml->destroy ( );    
    ?>
    

    In der xml.class.php steht die ganze Logik drin, die Dir Dein Xml-File zerpflückt. Sorry für das blöde Beispiel, ich habe die Struktur des XML jetzt nicht sehr glorreich gewählt, da menüs mit mehr als 2 Ebenen da n bissl schlecht machbar wären. Aber zum zeigen, sollte es reichen.

    Schau Dir am besten dazu in der PHP-Doku mal folgende Funktionen an:
    xml_set_object()
    xml_set_character_data_handler()
    xml_set_element_handler()

    Das Prinzip ist so, dass Du nen Handler definierst für öffnende Tags, CharacterData-Bereiche (alles zwischen öffnendem und schließendem Tag) und schließende Tags.

    Ich hoffe das Dir das irgendwie hilft.
    ** Um das zu testen, muss Expat installiert sein. Das ist aber eigentlich Standard.

    Gruß,
    mid



  • Puh, da arbeite ich mich mal durch...

    Wir erstelle nämlich gerade ein downloadarchiv, und das soll programminfos mit xmls einlesen können.

    Ok, Danke!!!



  • Dann solltest Du es auf jeden Fall so machen. Ist im Prinzip nicht so schwer, wenn man einmal hinter gestiegen ist. 🙂

    Viel Erfolg,
    mid



  • hmm... komisch, ist das bei dir auchso, dass der ganze xml text angezeigt wird?

    Eigendlich wollte ich die variale:
    XML_DIZ_INFO->Program_Info->Program_Name

    aus dieser xml fischen: http://www.filesforfree.de/test.xml

    kannste mir da nochmal schnell sagen wie das geht?



  • Weil heut Samstag ist. 😃

    Du musst im Prinzip nur die xml.class.php von weiter oben ändern:

    <?php
        class XML
        {
            var $parser;
            var $xml_file;
            var $html;
            var $open_tag;
            var $close_tag;
            var $open_flag = Array();
    
            function XML ( $file = null )
            {
                $this->parser = "";
                $this->html = "";
    
                if ( $file != "" )
                    $this->xml_file = $file;
    
                $this->parser = xml_parser_create ( );
    
                $this->open_tag = Array ( "menu" => "<table cellspacing='0' cellpadding='2' border='0'><tr>",
                                    "item" => "<td valign='top'><font size='3'>",
                                    "subitem" => "<br /><font size='2'>"
                                 );            
    
                $this->close_tag = Array ( "menu" => "</tr></table>",
                                    "item" => "</font></td>",
                                    "subitem" => "</font>"
                                 );            
            }
    
            function destroy ( )
            {
                xml_parser_free ( $this->parser );
            }
    
            function element_start ( $parser, $name, $attrib )
            {
                // diese Methode wird immer aufgerufen, wenn der Parser über ein öffnendes Tag läuft
                // $name ist der Elementname
                // $attrib ist im besten Falle ein assoziatives Array mit den ganzen Attributen
                if( $name=='Program_Name' )
                {
                    // wenn Du in diese if-Klausel kommst, dann bist Du im XML-Baum im Tag <Program_Name>
                    // mach hier damit, was Du willst
                    echo '<b>Programm-Name: ';
                    $this->open_flag['progname'] = true;
                }
            }
    
            function element_close ( $parser, $name )
            {
                // diese Methode wird immer aufgerufen, wenn der Parser über ein schließendes Tag läuft
                if( $name=='Program_Name' )
                {
                    // wenn Du in diese if-Klausel kommst, dann bist Du im XML-Baum im Tag </Program_Name>
                    // mach hier damit, was Du willst
                    echo '</b>';
                }
            }
    
            function element_data ( $parser, $data )
            {
                // hier werden alle Daten behandelt, die zwischen einem
                // öffnenden und schließenden Tag des gleichen Elementes stehen
                if( $this->open_flag['progname'] == true )
                {
                    echo $data;
                    unset( $this->open_flag['progname'] );
                }
            }
    
            function parse ( )
            {
                xml_set_object ( $this->parser, &$this );
                xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
                xml_set_character_data_handler ( $this->parser, "element_data" );
                xml_set_element_handler ( $this->parser, "element_start", "element_close" );
    
                if (  !($fp = fopen ( $this->xml_file, "r" ))  )
                    die ( "Opening XML-File failed!\n" );
    
                while (  $data = fread ( $fp, 2048 ) )
                {
                    if ( !xml_parse ( $this->parser, $data, feof($fp) )  )
                    {
                        die(sprintf("XML error: %s at line %d",
                                        xml_error_string( xml_get_error_code($this->parser)),
                                        xml_get_current_line_number($this->parser)));
                    }
                }
            }
        }
    ?>
    

    Und noch eine Bitte, verwenden bitte in Deiner XML-Datei nicht den Zeichensatz "windows-1252". Das kann bei manchen Parsern Probs machen. Günstig ist immer "ISO-8859-1" (das ist Latin 1) oder "UTF-8" o.ä

    Gruß,
    mid



  • Coooool, danke! Genau das hab ich gesucht!!!!



  • um XML darzustellen kann man fei auch die style-tags verwenden... (dann kann man im browser die xml-datei aufrufen, und bekommt ne webseite raus)


Anmelden zum Antworten