Verständnissproblem: XML(Datensammlung) -> PHP -> XHTML
Jeena Paradies
- xml
0 gant0 molily0 molily0 Jeena Paradies0 molily
Hallo,
Also ich versuche schon seit einer Weile dahinterzukommen wie das ganze zeug mit XML funktioniert. Dieses Forum hier legt seine Daten ja auch in XML Dateien ab und nicht in einer Datenbank.
Also genau so was habe ich auch vor. Von Amazon bekomme ich eine XML Datei die daten zu einem oder mehreren Büchern enthält:
----------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<ProductInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xml.amazon.com/schemas3/dev-lite.xsd">
<Request>
<Args>
<Arg value="Opera/7.54 (X11; Linux i686; U) [de]" name="UserAgent"></Arg>
<Arg value="1ETSV5C3MMZ4SRG22NMW" name="RequestID"></Arg>
<Arg value="0439139597" name="AsinSearch"></Arg>
<Arg value="us" name="locale"></Arg>
<Arg value="D15GA1WLALWF2H" name="dev-t"></Arg>
<Arg value="jeenaparadies-21" name="t"></Arg>
<Arg value="xml" name="f"></Arg>
<Arg value="lite" name="type"></Arg>
</Args>
</Request>
<Details url="http://www.amazon.com/exec/obidos/ASIN/0439139597/jeenaparadies-21?dev-t=D15GA1WLALWF2H%26camp=2025%26link_code=xm2">
<Asin>0439139597</Asin>
<ProductName>Harry Potter and the Goblet of Fire (Book 4)</ProductName>
<Catalog>Book</Catalog>
<Authors>
<Author>J. K. Rowling</Author>
<Author>Mary GrandPré</Author>
</Authors>
<ReleaseDate>08 July, 2000</ReleaseDate>
<Manufacturer>Scholastic</Manufacturer>
<ImageUrlSmall>http://images.amazon.com/images/P/0439139597.01.THUMBZZZ.jpg</ImageUrlSmall>
<ImageUrlMedium>http://images.amazon.com/images/P/0439139597.01.MZZZZZZZ.jpg</ImageUrlMedium>
<ImageUrlLarge>http://images.amazon.com/images/P/0439139597.01.LZZZZZZZ.jpg</ImageUrlLarge>
<Availability>Usually ships within 24 hours</Availability>
<ListPrice>$25.95</ListPrice>
<OurPrice>$17.65</OurPrice>
<UsedPrice>$3.74</UsedPrice>
</Details>
</ProductInfo>
----------------------------------------------------------
Jetzt will ich zum Beispiel das kleine Bild den Namen des Buches und den Autor auf meiner Seite anzeigen lassen. Wie kann ich da am besten vorgehen? Also ich habe wirklich keine Ahnung wie ich an die Sache rangehen soll. Soll ich das wirklich mit regulären Ausdrücken rausfischen? Das wäre bei größeren Datenmängen (sprich mehreren Büchern) ganz schön aufwendig denke ich.
Grüße
Jeena Paradies
Hallo
Dazu kannst Du XSL-Stylesheets verwenden, diese enthalten Dein XHTML-Code und XSL-Tags, über welche Du auf alle Knoten (Blätter) Deines XML-Dokumentes zugreifen kannst. SelfHTML bietet im XML Teil dazu jede Menge Informationen. Wie Du dann mit PHP die Transformation konkret vornimmst, kann ich Dir leider nicht sagen. In JAVA geht das mit JAXP etc.
Grüsse
gant
Hallo,
Dazu kannst Du XSL-Stylesheets verwenden, diese enthalten Dein XHTML-Code und XSL-Tags, über welche Du auf alle Knoten (Blätter) Deines XML-Dokumentes zugreifen kannst. SelfHTML bietet im XML Teil dazu jede Menge Informationen. Wie Du dann mit PHP die Transformation konkret vornimmst, kann ich Dir leider nicht sagen. In JAVA geht das mit JAXP etc.
Ok danke schon mal, jetzt habe ich viel in http://de.selfhtml.org/xml/darstellung/xsltbeispiele.htm gelesen und ich denke dass ich so ein stylesheet schon schreiben könnte, auch das mit der DTD würde ich unter Umständen hinbekommen, aber wer macht mir denn dann jetzt aus diesem XML unter zuhilfename von XSL(T) ein Kurzes Stück code?
Ich bekomme ja den im ersten Posting genannten Code. Davon benötige ich aber auch nicht alles sondern ich will davon ungefär so eine ausgabe:
<a href="http://www.amazon.com/exec/obidos/ASIN/0439139597/jeenaparadies-21?dev-t=D15GA1WLALWF2H%26camp=2025%26link_code=xm2"><img src="http://images.amazon.com/images/P/0439139597.01.THUMBZZZ.jpg" alt=""></a> Harry Potter and the Goblet of Fire (Book 4) von J. K. Rowling und Mary GrandPré
Grüße
Jeena Paradies
Hallo,
Jetzt will ich zum Beispiel das kleine Bild den Namen des Buches und den Autor auf meiner Seite anzeigen lassen. Wie kann ich da am besten vorgehen? Also ich habe wirklich keine Ahnung wie ich an die Sache rangehen soll. Soll ich das wirklich mit regulären Ausdrücken rausfischen? Das wäre bei größeren Datenmängen (sprich mehreren Büchern) ganz schön aufwendig denke ich.
Wenn die PHP-Extension DOMXML (http://de3.php.net/manual/en/ref.domxml.php) auf dem Server aktiviert ist und die PHP-Version relativ neu ist, kannst du z.B. so vorgehen, um den Inhalt eines Elements auszulesen:
$dom = domxml_open_mem($s, DOMXML_LOAD_PARSING, $error);
// var_dump($dom); print_r($error);
if ($dom and !$error) {
$productname_elements = $dom->get_elements_by_tagname('ProductName');
$productname_element = $productname_elements[0];
$productname_textnode = $productname_element->first_child();
$productname = $productname_textnode->node_value();
// $productname ist ein UTF-8-kodierter String, weil der Baum aus kanonischem XML erstellt wurde. Konvertierung zu ISO-8859-1 mit:
$productname = utf8_decode($productname);
echo($productname);
}
$s ist hier der String mit dem XML-Dokument. Die anderen Elemente kannst du nach demselben Schema auslesen: Elementknoten nach dem Tagnamen mit get_elements_by_tagname lokalisieren (diese Methode funktioniert auch für Elementknoten), das erste Arrayelement wählen (ein Details-Element hat anscheinend sowieso nie zwei Elemente desselben Typs), den ersten Kindknoten wählen (den Textknoten) und dessen node_value abfragen.
(Es kann sein, dass der obige Code erst ab PHP 4.3.6 funktioniert...)
Wenn du DOMXML nicht zur Verfügung hast, kannst eventbasiert mit Expat arbeiten (http://de3.php.net/manual/en/ref.xml.php). Diese Funktionen sind im Gegensatz zu DOMXML standardmäßig aktiviert.
Du brauchst (quick'n'dirty) nur zwei Event-Handler, wenn im XML-Dokument die Daten eines Artikels enthalten sind: Einen Character-Data-Handler, der jeden Textknoteninhalt in eine globalen Variable schreibt (und überschreibt), und einen End-Tag-Handler, der immer dann, wenn ein Element geschlossen wird, dessen Inhalt dich interessiert, den in der globalen Variable zwischengespeicherten Textinhalt in einem Array sichert. Dann hast du nach dem Parsen des Dokuments alle gewünschten Daten zusammen.
Bei gewünschter Zuverlässigkeit und komplizierterem Markup wird die Programmlogik entsprechend aufwändiger. Man muss dann mit Abfragen arbeiten, die je nach dem jeweiligen Status (werden gerade Token innerhalb eines Details-Elements bearbeitet?) die Zeichendaten unter dem Index des jeweiligen Elementnamens sichern.
Wenn die von Amazon zurückgegebenen XML-Dateien immer gleich aussehen und dermaßen simpel sind, dann sind reguläre Ausdrücken möglicherweise brauchbar. Auch bei mehreren Datensätzen pro XML-Dokument kann diese Methode hinreichend zuverlässig sein, solange du dich auf die Dokumentstruktur verlassen kannst.
Mathias
Falls du PHP 5 zur Verfügung hast, gestaltet sich das Unternehmen freilich einfacher, dort steht dir http://de3.php.net/manual/en/ref.simplexml.php zur Verfügung. Mit SimpleXML macht man solche Aufgaben mit links und im Handumdrehen (tm).
PHP 5 hat auch eine besseren DOM-Unterstützung: http://de3.php.net/manual/en/ref.dom.php. Das Prinzip ist dasselbe wie bei DOMXML in PHP 4, die Methodennamen sind nur anders (nämlich DOM-konform).
jeenaparadies.de meldet PHP 4.2.2... :(
Mathias
Hallo,
Das wäre wirklich optimal, aber wie du ja schon gesehen hast habe ich 4.2.2
Ich hab grad ne E-Mail an meinen Provider geschickt mit der Frage wann ich mit PHP 5 rechnen kann. Sonst macht er ja auch alles für mich, vielleicht spielt er es ja drauf ...
Grüße
Jeena Paradies
Hallo,
Vielen Dank für die gute erklärung.
$dom = domxml_open_mem($s, DOMXML_LOAD_PARSING, $error);
[...]
Das wäre mir eigentlich das liebste weil ich das sehr gut navollziehen kann was da passiert. Ich habe mal die Datei in einen String $s rein und dann danach deinen Code ausführen lassen, doch leider kam diese Warnung:
Warning: domxml_open_mem() expects at most 2 parameters, 3 given in /home/vhosts/jeenaparadies.clever-webspace.de/var/www/html/jeenas-home/phpinfo.php on line 38
Und es wurde sonst nichts ausgegeben. In http://de3.php.net/manual/en/function.domxml-open-mem.php sind aber drei Parameter erlaubt und es steht dort dass diese Funktion seit PHP 4.2.1 geht und ich habe auf meinem Server 4.2.2 Woran könnte es liegen dass diese Warnung erzeugt wird?
Grüße
Jeena Paradies
Hallo,
$dom = domxml_open_mem($s, DOMXML_LOAD_PARSING, $error);
[...]
Das wäre mir eigentlich das liebste weil ich das sehr gut navollziehen kann was da passiert. Ich habe mal die Datei in einen String $s rein und dann danach deinen Code ausführen lassen, doch leider kam diese Warnung:Warning: domxml_open_mem() expects at most 2 parameters, 3 given in /home/vhosts/jeenaparadies.clever-webspace.de/var/www/html/jeenas-home/phpinfo.php on line 38
Und es wurde sonst nichts ausgegeben.
Da musst du jeden einzelnen Schritt überprüfen, indem du dir die Variablen mit var_dump() ausgeben lässt.
In http://de3.php.net/manual/en/function.domxml-open-mem.php sind aber drei Parameter erlaubt und es steht dort dass diese Funktion seit PHP 4.2.1 geht und ich habe auf meinem Server 4.2.2 Woran könnte es liegen dass diese Warnung erzeugt wird?
Die gesamte PHP-Extension war immer »experimentell«. Das heißt, von einer PHP-Version auf die andere wurden Funktioen hinzugefügt und gelöscht und in ihrem Verhalten geändert. Das wurde nirgendwo dokumentiert. Der fehlerfreie Zugriff auf die Parserfehler über den dritten Parameter ($error) ist (soweit ich mich richtig erinnere) erst ab 4.3.6 möglich. Du kannst einmal domxml_open_mem($s) ausprobieren, denn lediglich der erste Parameter war (meiner Erinnerung nach) immer obligatorisch, der dritte kam erst spät hinzu. DOMXML_LOAD_PARSING als Parsing-Modus ist meines Wissens Standard, insofern kann der Parameter in dem Fall weggelassen werden.
Parsing-Fehler gibt domxml_open_mem() in dem Fall als Warnungen aus, du kannst diese nicht direkt auslesen (höchstens über Output-Buffer) und müsstest dich somit darauf verlassen, dass beim Parsen keine Fehler auftreten. Du kannst also nur mit if ($dom) ... überprüfen, ob der DOM-Baum grundsätzlich erzeugt wurde, dann ob deine get_elements_by_id die gesuchten Elemente zurückgegeben hat, ob entsprechende Knoten existieren usw.
Ich habe mir 4.2.2 noch einmal installiert: Mit $dom = domxml_open_mem($s); wird am Ende korrekterweise »Harry Potter and the Goblet of Fire (Book 4)« ausgegeben. Wahrscheinlich sind also keine besonderen Anpassungen notwendig.
Mathias
Hallo,
Ich habe mir 4.2.2 noch einmal installiert: Mit $dom = domxml_open_mem($s); wird am Ende korrekterweise »Harry Potter and the Goblet of Fire (Book 4)« ausgegeben. Wahrscheinlich sind also keine besonderen Anpassungen notwendig.
Super funktioniert prima! Das mit den Fehlermeldungen kriege ich noch irgendwie in den Griff, aber das ist sowieso nicht so schlimm denn der code wird nur im Admincenter ausgeführt, es sieht also nur höchstens der der die Seite upgradet wenn das XML von Amazon mal nicht korrekt sein sollte. Ich habe mir jetzt mal ne funktion daraus gebaut:
function get_xml_data($tag, $s) {
$dom = domxml_open_mem($s);
if ($dom) {
$elements = $dom->get_elements_by_tagname($tag);
$element = $elements[0];
$textnode = $element->first_child();
$data = $textnode->node_value();
$data = utf8_decode($data);
return($data);
}
else return false;
}
Ich muss aber da, wenn ich das noch wo anders benutzen wollen würde, mir überlegen was ich mache wenn es zum Beispiel zwei Autoren sind. Irgendwie muss ich es schaffen dass dann ein array mit den zwei Autoren ausgegeben wird.
Grüße
Jeena Paradies