philippo: XML Parse problem

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

  1. 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

    --
    The only program that runs perfectly every time, is a virus.
    1. 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