XML, PHP4 & XPath: Elementpfad auslesen

T

t_soul

Mitglied
Thread Starter
Dabei seit
11.06.2005
Beiträge
20
Reaktionspunkte
0
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
 
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. :)
 
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
 
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. :)
 
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
 
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
 
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
 
Zurück
Oben Unten