XML Parse problem
philippo
- php
Hallo
ich habe vor einigen Tage angefangen mit XML. Nun möchte ich die folgende Datei in PHP auslesen lassen.
<?xml version="1.0"?>
<news>
<story>
<id>1</id>
<storry>Hallo1</storry>
</story>
<story>
<id>2</id>
<storry>Hallo2</storry>
</story>
</news>
Nun möchte ich, abhängig von der ID die storry dazu anzeigen. Sprich wennd er Uesr 2 Eingibt soll, Hallo2 erscheinen und so weiter. Da ich noch realtiv neu auf dem Gebiet bin, hoffe ich, dass es nciht allzu schwierig ist ;-)
Gruß
philippo
Halihallo philippo
ich habe vor einigen Tage angefangen mit XML. Nun möchte ich die folgende Datei in PHP auslesen lassen.
http://www.php.net/domxml (EXPERIMENTAL!)
http://www.php.net/xml
Nun möchte ich, abhängig von der ID die storry dazu anzeigen. Sprich wennd er Uesr 2 Eingibt soll, Hallo2 erscheinen und so weiter. Da ich noch realtiv neu auf dem Gebiet bin, hoffe ich, dass es nciht allzu schwierig ist ;-)
Depends. Lies die vorher verlinkten Ressourcen und mach dich mit dem
Interface/Schnittstelle zu XML-Dokumenten vertraut.
Dann würde ich dir empfehlen das XML-Dokument wie folgt zu ändern:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<news>
<story id="1">Hallo1</story>
<story id="2">Hallo2</story>
</news>
Jetzt liesse sich die Story zu einer ID über XML-DOM sehr, sehr
einfach auslesen:
---pseudo-code--
my $story = $doc->get_element_by_id( $id )->child_nodes()->item(0)->node_value();
---
Dein XML-Dokument liesse sich natürlich auch über XML-DOM oder einer
selbstgeschriebenen Expat-Parser-Extension auslesen, nur wird es
da etwas komplexer, da die Struktur bezüglich der Anfrage nicht
"optimiert" ist. Du müsstest in deinem Beispiel durch alle story
Elemente durchgehen (get_elements_by_tag_name('story')) und bei jedem
überprüfen, ob ein ChildNode namens "id" existiert, falls ja ob
dessen ChildNode (Text) mit der $id übereinstimmt und dann den
next_sibling() vom <id>-Tag ausliest (das wäre dann <storry>,
falls das Dokument _immer in dieser Form vorliegt und die
Elementreihenfolge etc. nicht geändert wird_) und von diesem den
unterliegenden TextNode (was dann eben der Text zu der Storry ist,
in deinem Fall "Hallo1" oder "Hallo2", je nach $id).
Viele Grüsse
Philipp
Hallo,
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<news>
<story id="1">Hallo1</story>
<story id="2">Hallo2</story>
</news>Jetzt liesse sich die Story zu einer ID über XML-DOM sehr, sehr
einfach auslesen:
So einfach ist es nicht, denn dass id ein Attribut vom Typ ID ist, muss aus der DTD hervorgehen, sonst findet get_element_by_id das Element nicht.
---pseudo-code--
my $story = $doc->get_element_by_id( $id )->child_nodes()->item(0)->node_value();
Das lässt sich übrigens einfacher mit get_content lösen. Zum Beispiel so:
$xml_file='news.xml';
$id='a1';
$dom = @domxml_open_file(realpath($xml_file), DOMXML_LOAD_PARSING, $error);
if ($dom and !$error) {
$story_element = $dom->get_element_by_id($id);
if ($story_element) {
$story_text = $story_element->get_content();
echo($story_text);
} else {
echo('<p>Die Story-ID '.$id.' konnte nicht gefunden werden.</p>');
$story_text=false;
}
$dom->free();
} else {
echo('<p>Fehler beim Einlesen/Verarbeiten des XML-Dokuments '.$xml_file.'.</p>');
/* Im $error-Array werden Parsing-Fehler gespeichert */
// if ($error) print_r($error);
}
Die Error-Behandlung bei DOMXML_LOAD_PARSING geht mit 4.3.4 nicht, mit 4.3.6 schon. Ausreichen würde natürlich $dom = @domxml_open_file(realpath($xml_file)); if ($dom) { ... }, nur dann lässt sich nicht unterscheiden, ob schon beim Parsen Fehler auftreten.
Dann gibt es noch einen weiteren Fallstrick: Wenn nicht gerade DOMXML_LOAD_VALIDATING als zweiter Parameter von domxml_open_file/_mem angegeben ist, muss die DTD im Dokument selbst enthalten sein, damit das Attribut id als ID-Attribut erkannt wird (siehe oben). Also:
<?xml ... ?>
<!DOCTYPE news [
<!ELEMENT news (story)+>
<!ELEMENT story (#PCDATA)>
<!ATTLIST story
id ID #REQUIRED
]>
...
Mit DOMXML_LOAD_VALIDATING kann die Dokumenttyp-Deklaration auch <!DOCTYPE news SYSTEM "news.dtd"> lauten (bzw. bei domxml_open_mem ein absoluter Pfad), die DTD also eine externe Datei sein. Dabei wird aber das ganze Dokument gegen die DTD validiert (DOMXML_LOAD_PARSING findet nur Wohlgeformtheitsfehler), was man meistens nicht will und was unnötig Zeit kostet.
Vielleicht sollte man in solchen Fällen wirklich mit den expat-Funktionen arbeiten http://de3.php.net/manual/en/ref.xml.php, die laufen wahrscheinlich schneller als validierende domxml_open_*. Vor allem ist es bei solchen einfachen Dokumentstrukturen entsprechend einfach, den Textinhalt eines story-Elements mit einer bestimmten ID zu finden (im Start-Tag-Handler einen Flag setzen, wenn die gesuchte ID gefunden wird und im Character-Data-Handler den Elementinhalt speichern, wenn der Flag gesetzt ist).
Übrigens darf ein Attribut vom Typ ID nicht mit einer Zahl beginnen.
Mathias