Verzweifele mit dom xpath->query
Matthias
- php
Hallo,
ich versuche auf ein XML-Dokument mittels Dom und xpath zuzugreifen. Nachdem das alles nicht funktioniert hat, habe ich mir das Beispiel aus der php.net doku gezogen, und das klappt wunderbar:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
]>
<book id="listing">
<title>My lists</title>
<chapter id="books">
<title>My books</title>
<para>
<informaltable>
<tgroup cols="4">
<thead>
<row>
<entry>Title</entry>
<entry>Author</entry>
<entry>Language</entry>
<entry>ISBN</entry>
</row>
</thead>
<tbody>
<row>
<entry>The Grapes of Wrath</entry>
<entry>John Steinbeck</entry>
<entry>en</entry>
<entry>0140186409</entry>
</row>
<row>
<entry>The Pearl</entry>
<entry>John Steinbeck</entry>
<entry>en</entry>
<entry>014017737X</entry>
</row>
<row>
<entry>Samarcande</entry>
<entry>Amine Maalouf</entry>
<entry>fr</entry>
<entry>2253051209</entry>
</row>
<!-- TODO: I have a lot of remaining books to add.. -->
</tbody>
</tgroup>
</informaltable>
</para>
</chapter>
</book>
$doc = new DOMDocument;
// We don't want to bother with white spaces
$doc->preserveWhiteSpace = false;
$doc->Load('book.xml');
$xpath = new DOMXPath($doc);
// We starts from the root element
$query = '//book/chapter/para/informaltable/tgroup/tbody/row/entry[. = "en"]';
$entries = $xpath->query($query);
foreach ($entries as $entry) {
echo "Found {$entry->previousSibling->previousSibling->nodeValue}," .
" by {$entry->previousSibling->nodeValue}\n";
}
Ich erhalte als Ergebnis "Found The Grapes of Wrath, by John Steinbeck Found The Pearl, by John Steinbeck". Super.
Mit meinem Dokument klappt es aber nicht. Hauptunterschied den ich sehe, ist der Kopf der Datei. Ich benutze statt
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
]>
<book id="listing">
den Aufbau
<?xml version="1.0" encoding="iso-8859-1"?>
<?oxygen RNGSchema="http://www.oasis-open.org/docbook/xml/5.0/rng/docbook.rng" type="xml"?>
<book
version="5.0"
xml:id="Id0"
xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink">
Wenn ich oben geschilderte xml-Datei nun mit diesem Kopf ausstatte, erhalte ich keine Ausgabe, nicht mal einen Error oder ein Warning.
Ich habe nun verschiedenes probiert (Namespace Registrierung, den oxygen-tag rausnehmen,...), bekomme aber kein Ergebnis.
Wenn ich php wie folgt ändere:
[...]
$query = '/*';
[...]
echo "<br>".$entry->nodeName." = ".$entry->nodeValue;
[...]
erhalte ich
book = My listsMy booksTitleAuthorLanguageISBNThe Grapes of WrathJohn Steinbecken0140186409The PearlJohn Steinbecken014017737XSamarcandeAmine Maalouffr2253051209
aber sobald ich den * gegen book, oder irgendeinen anderen Tag-Namen austausche (wie bespielseise '//title'), erhalte ich wieder keine Ausgabe.
Kann mir hier jemand verraten was ich falsch mache oder vergesse?
Vielen Dank.
Gruß
Matthias
Ahoi,
<?oxygen RNGSchema="http://www.oasis-open.org/docbook/xml/5.0/rng/docbook.rng" type="xml"?>
<book
version="5.0"
xml:id="Id0"
xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink">[/code]
auch, wenn du den Namespace entfernst. Erweitere das funktionierende Dokument Schrittweise.
Dank und Gruß,
Hallo,
nach vielem hin und her habe ich nun eine Lösung gefunden:
Man muss einen Default-Namespace definieren.
$xpath = new DOMXPath($domdoc);
$query = '/child::*[1]/info/title';
$entries = $xpath->query($query);
echo "<br>--->".$entries->item(0)->nodeName;
echo "<br>--->".$entries->item(0)->nodeValue;
liefert kein Ergebnis, egal welche Deklarationen man in der xml hinzufügt oder weglässt.
$xpath = new DOMXPath($domdoc);
$xpath->registerNamespace("default","http://docbook.org/ns/docbook");
$query = '/child::*[1]/default:info/default:title';
$entries = $xpath->query($query);
echo "<br>--->".$entries->item(0)->nodeName;
echo "<br>--->".$entries->item(0)->nodeValue;
liefert hingegen das gewünschte Ergebnis.
Statt default kann man auch fizzlibuzzli oder sonstwas eingeben, hauptsache man hat einen default-ns definiert.
Vielleicht hilft dies irgendwem etwas weniger Frust aufzubauen als ich.
Gruß
Matthias