lixx: ID-Mapping mit XML

Hallo liebe Leut’!

Bitte helft mir. Ich bin schier am verzweifeln!

Ich versuche eine language-Klasse in PHP (5.0.x) zu basteln, die XML-Dateien ausliest und in einer Variable speichert. Mein Problem liegt nun darin, dass sich die einzelnen Nodes nicht per getElementById() der DOM Function ansprechen lassen. Nach langem Suchen bin ich auf diese Seite http://php5.bitflux.org/xmlonspeed/slide_24.php gestoßen und möchte daher auf jeden Fall diese Methode benutzen.

Nun ist es so, dass man, um diese Methode nutzen zu können, bei der DOM Function eine ID deklarieren muss. (Auch schon gefunden ;) http://wiki.flux-cms.org/display/BLOG/GetElementById+Pitfalls). Ich habe mich dabei für "xml:id" entschieden.

Hier einmal kurz die Dateien...

de.lang.xml:
-------------------------------------------
<?xml version="1.0" encoding="utf-8" ?>
<xml>
 <locale lang="de">
  <str xml:id="myID1">aaa</str>
  <str xml:id="myID2">bbb</str>
 </locale>
</xml>
-------------------------------------------

index.php:
-------------------------------------------
// Lade Sprachdatei
$lf = new DOMDocument('1.0', 'UTF-8');
$lf->preserveWhiteSpace = false;
$lf->load('de.lang.xml');

// Erstelle neues XML-Dokument
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->preserveWhiteSpace = false;
$xml->appendChild(new DOMElement('xml'));

// Führe Sprach-Nodes mit neuem XML-Dokument zusammen.
// Das ist auf jeden Fall notwendig, da mehrere Sprachdateien
// nacheinander zu laden sein sollen.
$xml->documentElement->appendChild(
 $xml->importNode($lf->documentElement->firstChild, true));

echo $xml->getElementById('myID2')->nodeValue . "\n";

$x = $xml->saveXML();

header('Content-Type: application/xml; charset=UTF-8');
header('Content-Length: '.strlen($x));

print($x);

exit;
-------------------------------------------

Jetzt passiert folgendes: Beim Aufruf von echo $xml->getElementById('myID2')->nodeValue passiert nix. Er findet diese ID nicht. Wenn ich nun aber $lf->getElementById('myID2')->nodeValue verwende, also die Spach-Datei direkt, dann klappt es.

$xml->saveXML() gibt mir aber den vollständigen und richtigen Baum mit xml:id wieder.

Warum funktioniert das nicht oder wie kann man das sonst noch lösen? Was ich auf jeden Fall benötige ist das mergen von mehreren XML-Dateien und Schleifen wie ...

for ($i=0; $i<$xml->childNodes->length; $i++)
{
 $cn = self::$XML->importNode($xml->childNodes->item($i), true);
 $xml_data->appendChild($cn);
}

... möchte ich auch vermeiden.

Danke euch im Voraus!

lg lixx

  1. Hallo,

    Dein Code, den Du hier gepostet hast, funktioniert 1:1 bei mir. Ich habe lediglich die Header()-Aufrufe entfernt, weil ich auf der Kommandozeile arbeite, aber wenn ich Dein PHP-Script ansonsten unverändert aufrufe, erhalte ich als Ausgabe:

    ----------- schnipp ----------------
    bbb
    <?xml version="1.0" encoding="UTF-8"?>
    <xml><locale lang="de"><str xml:id="myID1">aaa</str><str xml:id="myID2">bbb</str></locale></xml>
    ----------- schnapp ----------------

    Und ja, da steht $xml->getElementById, nicht $lf->getElementById.

    Welche PHP-Version hast Du? Ich habe:

    PHP 5.2.6RC1-pl1-gentoo with Suhosin-Patch 0.9.6.2 (cli) (built: Mar 22 2008 17:21:59)

    Außerdem verwendet mein PHP (siehe phpinfo) die libxml-Version 2.6.30.

    Ich würde stark vermuten, dass das ein Bug in der libxml2 ist, der inzwischen korrigiert wurde. Das ganz sieht stark nach dem Bug #314358 aus, der in 2.6.21 korrigiert wurde - meine Vermutung ist, dass Deine Version geringer ist.

    Viele Grüße,
    Christian

    1. Welche PHP-Version hast Du? Ich habe:

      PHP 5.2.6RC1-pl1-gentoo with Suhosin-Patch 0.9.6.2 (cli) (built: Mar 22 2008 17:21:59)

      Außerdem verwendet mein PHP (siehe phpinfo) die libxml-Version 2.6.30.

      Danke für Deine Antwort. Wird dann wahrscheinlich an der Version liegen. Ich tümple noch mit 5.0.irgendwas rum. Ob ich ein Update durchführen kann, weiß ich noch nicht. Daher wären mir weitere Tipps lieb!

      Z.B. funzt es bei mir auch, wenn ich für $xml folgendes verwende:
      ------------------------------------------
      $xml = new DOMDocument('1.0', 'UTF-8');
      $xml->preserveWhiteSpace = false;

      $xml->loadXML('
       <!DOCTYPE xml [
        <!ELEMENT xml (locale)*>
        <!ELEMENT locale (str)*>
        <!ATTLIST str
         id ID #IMPLIED>
       ]>
       <xml></xml>
      ');
      ------------------------------------------

      Dann allerdings, darf das ID-Attribut nur id="" lauten und nicht xml:id="".

      Warum noch weitere Tipps?

      Wenn ich nun noch eine Datei (selber Aufbau) hinzufüge, mit ...
      ------------------------------------------
      $xml->documentElement->appendChild(
       $xml->importNode($lf2->documentElement->firstChild, true));
      ------------------------------------------
      ... dann klappt's wieder nicht :(

      In dem Fall sieht die XML-Datei folgend aus:
      ------------------------------------------
      <?xml version="1.0" encoding="utf-8" ?>
      <!DOCTYPE xml [
      <!ELEMENT xml (locale)*>
      <!ELEMENT locale (str)*>
      <!ATTLIST str id ID #IMPLIED>
      ]>
      <xml>
       <locale lang="de">
        <str id="myID1">aaa</str>
        <str id="myID2">bbb</str>
       </locale>
       <locale lang="de">
        <str id="myID3">ccc</str>
        <str id="myID4">ddd</str>
       </locale>
      </xml>
      ------------------------------------------

      lg lixx

      1. HA! Ich glaube ich hab es jetzt!

        Ich hatte einmal $xml->validate() dabei und einmal nicht. Mit funzt es jetzt :D

        lg lixx