XML, PHP4 & XPath: Elementpfad auslesen

Dieses Thema im Forum "Web-Programmierung" wurde erstellt von t_soul, 28.11.2005.

  1. t_soul

    t_soul Thread Starter MacUser Mitglied

    Beiträge:
    20
    Zustimmungen:
    0
    MacUser seit:
    11.06.2005
    Hallo!

    Ein (für Insider sicher kleines) Problem beschäftigt mich:
    Wie komme ich an den Pfad des aktuellen XML-Elements heran?

    Zuerst das Dokument einlesen, dann:

    $INV = "//OBJECTS/OBJECT/LOCAL_NUMBER"; // der gesuchte Pfad

    $JederKnoten = Xpath_eval($xpc, "//child::text()");
    foreach ($JederKnoten->nodeset as $Knoten) {
    ....$Inhalt = $Knoten->content; // das ist der Inhalt
    ....// Pfad $INV abfragen, aber wie???
    }



    Ich lese alle Elemente aus dem XML-Dokument aus. Bei bestimmten Elementen soll er die inhalte in eine mySQL-DB schreiben.

    Voraussetzung: XPath unter php4.3, domxml, kein SimpleXML.

    Danke! - Till
     
  2. dms

    dms Gast

    Ich vermute Du willst den absoluten Pfad um ihn in die DB einzutragen, oder? Ansonsten hast Du den aktuellen Knoten natürlich in . oder self::node().
    Den absoluten Pfad kann man jedoch nicht mit purem XPath ermitteln. XPath beschreibt ja nur den Weg zwischen zwei Positionen im Dokument. Wenn, dann bietet diese Möglichkeit wohl nur die Erweiterung die Du verwendest.

    Kannst Du dazu mal bitte einen Link posten? Ist mir leider unbekannt und interessiert mich. :)
     
  3. t_soul

    t_soul Thread Starter MacUser Mitglied

    Beiträge:
    20
    Zustimmungen:
    0
    MacUser seit:
    11.06.2005
    Hi dms,

    Ich vermute Du willst den absoluten Pfad um ihn in die DB einzutragen, oder?

    exakt! :)

    Ich bin jetzt ein _kleines_ Stück weiter:
    in XML:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <OBJECTS>

    <OBJECT>
    <OBJECT_ID>2824133</OBJECT_ID>
    <REGIST_NUM>2337/2001</REGIST_NUM>
    <LOCAL_NUMBER>02505</LOCAL_NUMBER>
    <TITLE>Geldbörse</TITLE>

    <COLL_OBJ>
    <INSTITUTION>Museum in der Runden Ecke - Sammlung</INSTITUTION>
    <SAMMLUNG>Film und Fotografie</SAMMLUNG>
    <BEREICH>Techn. Gerrät</BEREICH>
    </COLL_OBJ>

    <REAL_OBJ>
    <TITLE>Portemonnaie mit versteckter Kamera Tessina L</TITLE>
    </REAL_OBJ>

    <OBJ_VALUE>
    <VALUE>9</VALUE>
    <UNIT>cm</UNIT>
    <UNIT_NAME>Breite</UNIT_NAME>
    <OBJEKTTEIL>Gesamt</OBJEKTTEIL>
    </OBJ_VALUE>


    ergibt:

    OBJECTS/OBJECT/OBJECT_ID/..........2824133
    OBJECT/REGIST_NUM/..........2337/2001
    OBJECT/LOCAL_NUMBER/..........02505
    OBJECT/TITLE/..........Geldbörse
    OBJECT/COLL_OBJ/INSTITUTION/..........Museum in der Runden Ecke - Sammlung
    COLL_OBJ/SAMMLUNG/..........Film und Fotografie
    COLL_OBJ/BEREICH/..........Techn. Gerät
    COLL_OBJ/OBJECT/REAL_OBJ/TITLE/..........Portemonnaie mit versteckter Kamera Tessina L
    REAL_OBJ/OBJECT/OBJ_VALUE/VALUE/..........9
    OBJ_VALUE/UNIT/..........cm
    OBJ_VALUE/UNIT_NAME/..........Breite
    OBJ_VALUE/OBJEKTTEIL/..........Gesamt


    Der Code dazu ist:

    <?php
    $filename = "xml/Export1.xml";
    $xml = domxml_open_file($filename);
    $xpc = Xpath_new_context($xml);
    Xpath_register_ns($xpc, "x", "http://www.someplace.com");

    $JederKnoten = Xpath_eval($xpc, "//child::text()");
    /* ********** gesamtes Dokument durchlaufen *****************/
    foreach ($JederKnoten->nodeset as $Knoten) {
    $Inhalt = $Knoten->get_content(); // den Inhalt holen
    $Pfad0 = $Knoten->parent_node(); // Elternknoten holen
    $Pfad1 = $Pfad0->tagname(); // Bezeichnung des Knoten
    echo "<i>$Pfad1/</i>";
    echo "..........$Inhalt<br>\n";
    }
    /* *******************************************************/
    $xml->free();
    ?>


    Tja, in der ersten Sekunde freute ich mich. Aber das Ergebnis ist falsch! Er arbeitet nur stur alle Knoten ab. Das nützt mir also nichts.
    Und nur die öffnenden Knoten zu verwenden reicht auch nicht.
    Und an jedem Knoten, welcher einen Inhalt hat, rekursiv nach Eltern, Großeltern, Urgroßeltern suchen? Ja, aber wie?

    Till
     
  4. dms

    dms Gast

    Ach jetzt seh ich's erst. Die PHP-XPath-Funktionen hab ich vorher nie bemerkt. Ist ja cool! :) Ich dachte Du verwendest hier irgend eine PHP-Klasse aus dem Netz...

    Jetzt verstehe ich aber nicht was an der Lösung falsch ist. Sieht doch gut aus. Du erhältst den absoluten Pfad zum aktuellen Knoten. Das wolltest Du doch. :)
     
  5. t_soul

    t_soul Thread Starter MacUser Mitglied

    Beiträge:
    20
    Zustimmungen:
    0
    MacUser seit:
    11.06.2005
    Jetzt verstehe ich aber nicht was an der Lösung falsch ist. Sieht doch gut aus.

    Ja, auf den ersten Blick.
    Genau genommen stimmt schon die zweite Zeile nicht mehr, da fehlt OBJECTS.
    Und ab der 6. Zeile fehlt OBJECT.
    Und REAL_OBJ/OBJECT/OBJ_VALUE/VALUE/..........9 ist total falsch!
    Es beachtet eben auch die schließenden Elemente, so dass man am Ende ...OBJECT/OBJECTS erhält.
    Da sich die Elementbezeichnungen leider doppeln (z.B. ist TITEL doppelt vergeben), reichen mir die Elementnamen alleine nicht. Ich brauche den ganzen Pfad.
    Und mit einem Programm wie Navicat (navicat.de) wird das wohl auch nicht so einfach gehen. Hat da jemand Erfahrung? Die Demo läuft bei mir nicht, ich bekomme keine Verbindung zum Server hin.

    Till
     
  6. t_soul

    t_soul Thread Starter MacUser Mitglied

    Beiträge:
    20
    Zustimmungen:
    0
    MacUser seit:
    11.06.2005
    Nun klappt es (fast):

    habe testweise folgenden Code eingefügt:

    $PfadA = $Knoten->parent_node();
    $PfadA1 = $PfadA->node_name();

    if($PfadA->parent_node()){
    $PfadB = $PfadA->parent_node();
    $PfadB1 = $PfadB->node_name();

    if($PfadB->parent_node()){
    $PfadC = $PfadB->parent_node();
    $PfadC1 = $PfadC->node_name();

    if($PfadC->parent_node()){
    $PfadD = $PfadC->parent_node();
    $PfadD1 = $PfadD->node_name();

    if($PfadD->parent_node()){
    $PfadE = $PfadD->parent_node();
    $PfadE1 = $PfadE->node_name();
    }
    }
    }
    }


    (Ja, ich weiß, es geht auch rekursiv... War nur ein Test.)


    Damit erhalte ich nun:

    #document:OBJECTS:OBJECT:OBJECT_ID: ..........2824133
    #document:OBJECTS:OBJECT:REGIST_NUM: ..........2337/2001
    #document:OBJECTS:OBJECT:LOCAL_NUMBER: ..........02505
    #document:OBJECTS:OBJECT:TITLE: ..........Geldbörse
    OBJECTS:OBJECT:COLL_OBJ:INSTITUTION: ..........Museum in der Runden Ecke - Sammlung
    OBJECTS:OBJECT:COLL_OBJ:SAMMLUNG: ..........Film und Fotografie
    OBJECTS:OBJECT:COLL_OBJ:BEREICH: ..........Techn. Gerät
    OBJECTS:OBJECT:REAL_OBJ:TITLE: ..........Portemonnaie mit versteckter Kamera Tessina L
    OBJECTS:OBJECT:OBJ_VALUE:VALUE: ..........9
    OBJECTS:OBJECT:OBJ_VALUE:UNIT: ..........cm
    OBJECTS:OBJECT:OBJ_VALUE:UNIT_NAME: ..........Breite
    OBJECTS:OBJECT:OBJ_VALUE:OBJEKTTEIL: ..........Gesamt
    OBJECTS:OBJECT:OBJ_VALUE:VALUE: ..........10
    OBJECTS:OBJECT:OBJ_VALUE:UNIT: ..........cm


    Für die ersten Zeilen baue ich noch eine Kehrmaschine ein ;-)

    Till
     
  7. t_soul

    t_soul Thread Starter MacUser Mitglied

    Beiträge:
    20
    Zustimmungen:
    0
    MacUser seit:
    11.06.2005
    Nochmal ein eleganterer Nachtrag.
    Der gesamte Code, fett ist neu (Danke an Max):

    <?php
    $filename = "xml/Export1.xml";
    $xml = domxml_open_file($filename);
    $xpc = Xpath_new_context($xml);
    Xpath_register_ns($xpc, "x", "http://www.someplace.com");

    $JederKnoten = Xpath_eval($xpc, "//child::text()");
    /* ********** gesamtes Dokument durchlaufen *****************/
    foreach ($JederKnoten->nodeset as $Knoten) {
    $Inhalt = $Knoten->get_content(); // den Inhalt holen
    $Pfad = $Knoten->node_name(); // der erste Knotenname
    while ($Knoten = $Knoten->parent_node()) // alle Knoten von innen nach aussen abarbeiten
    $Pfad = $Knoten->node_name()."/".$Pfad; //

    if($Inhalt) {
    /***** hier nun $Inhalt und $Pfad in die Datenbank schreiben *****/
    echo "<i>$Pfad </i>"; // Kontrolle
    echo "..........$Inhalt<br>\n"; // Kontrolle
    }
    }
    /* *********************************************************/
    $xml->free();
    ?>


    damit wirft er das aus:
    #document/OBJECTS/OBJECT/OBJECT_ID/#text ..........2824133
    #document/OBJECTS/OBJECT/REGIST_NUM/#text ..........2337/2001
    #document/OBJECTS/OBJECT/LOCAL_NUMBER/#text ..........02505
    #document/OBJECTS/OBJECT/TITLE/#text ..........Geldbörse
    #document/OBJECTS/OBJECT/COLL_OBJ/INSTITUTION/#text ..........Museum in der Runden Ecke - Sammlung
    #document/OBJECTS/OBJECT/COLL_OBJ/SAMMLUNG/#text ..........Film und Fotografie
    #document/OBJECTS/OBJECT/COLL_OBJ/BEREICH/#text ..........Techn. Gerät
    #document/OBJECTS/OBJECT/REAL_OBJ/TITLE/#text ..........Portemonnaie mit versteckter Kamera Tessina L
    #document/OBJECTS/OBJECT/OBJ_VALUE/VALUE/#text ..........9
    #document/OBJECTS/OBJECT/OBJ_VALUE/UNIT/#text ..........cm
    #document/OBJECTS/OBJECT/OBJ_VALUE/UNIT_NAME/#text ..........Breite
    #document/OBJECTS/OBJECT/OBJ_VALUE/OBJEKTTEIL/#text ..........Gesamt


    Till
     
Die Seite wird geladen...