Ich habe ein XML-Dokument, an das ein Standard-Namespace angehängt ist, z. B.
%Vor%In Wirklichkeit ist dies ein komplexes XML-Dokument, das einem komplexen Schema entspricht. Meine Aufgabe ist es, einige Daten daraus zu analysieren. Um mir zu helfen, habe ich eine Kalkulationstabelle von XPath. Der XPath ist ziemlich tief verschachtelt, zB
%Vor%Die Person, die den XPath generiert, ist ein Experte im Schema, also gehe ich davon aus, dass ich sie nicht vereinfachen kann, oder benutze Objekt-Traversal-Shortcuts.
Ich benutze SimpleXML , um alles zu analysieren. Mein Problem hat damit zu tun, wie der Standard-Namespace behandelt wird.
Da auf dem Root-Element ein Standard-Namensraum existiert, kann ich nicht einfach
machen %Vor%Ich muss den Namespace registrieren , ihn einem Präfix zuweisen und dann den Präfix in meinem XPath, zB
%Vor%Das Hinzufügen der Präfixe wird auf lange Sicht nicht bewältigt werden können.
Gibt es eine geeignete Methode, um Standard-Namespaces zu verarbeiten, ohne dass Präfixe mit XPath verwendet werden müssen?
Die Verwendung eines leeren Präfixes funktioniert nicht ( $xml->registerXPathNamespace('', 'http://www.example.com/ns/1.0');
). Ich kann den Standard-Namespace ausstreichen, zB
Aber das ist das Problem.
Nach ein wenig Online-Lektüre ist dies nicht auf irgendeine bestimmte PHP- oder andere Bibliothek beschränkt, sondern auf XPath selbst - zumindest in XPath Version 1.0
XPath 1.0 enthält kein Konzept für einen "Standard" -Namespace. Unabhängig davon, wie die Elementnamen in der XML-Quelle angezeigt werden, müssen die Selektoren für sie in grundlegenden XPath-Selektoren vorangestellt werden, wenn sie an sie gebunden sind der Form ns:name
. Beachten Sie, dass ns
ein Präfix ist, das im XPath-Prozessor definiert ist, nicht durch das zu verarbeitende Dokument. Es hat also keine Beziehung dazu, wie xmlns
-Attribute in der XML-Darstellung verwendet werden.
Siehe z.B. diese Seite "Common XSLT-Fehler" , die über das nahe verwandte XSLT 1.0 spricht:
Um auf namespaced Elemente in XPath zuzugreifen, müssen Sie ein Präfix für ihren Namespace definieren. [...] Leider hat XSLT Version 1.0 kein Konzept ähnlich einem Standard-Namespace; Daher müssen Sie Namespace-Präfixe immer wieder wiederholen.
Laut einer Antwort auf eine ähnliche Frage enthält XPath 2.0 einen Begriff von "default namespace", und die oben verlinkte XSLT-Seite erwähnt dies auch im Zusammenhang mit XSLT 2.0.
Leider sind alle integrierten XML-Erweiterungen in PHP auf der libxml2 und libxslt Bibliotheken, die nur Version 1.0 von XPath und XSLT unterstützen.
Sie können also nicht nur das Dokument vorverarbeiten, um Namespaces zu verwenden, sondern auch einen XPath 2.0-Prozessor finden, den Sie mit PHP verbinden könnten.
(Nebenbei bemerkt, wenn Sie in Ihrem XML-Dokument nicht festgelegte Attribute haben, befinden sie sich technisch nicht im Standard-Namespace, sondern in keinem Namespace; siehe XML-Namespaces und nicht vordefinierte Attribute zur Diskussion dieser Kuriosität der Namespace-Spezifikation.
Gibt es eine geeignete Methode, mit Standard-Namespaces umzugehen, ohne dass dies erforderlich ist? Verwenden von Präfixen mit XPath?
Nein. Die richtige Methode zum Behandeln von any -Namespaces besteht darin, diesem Namespace einen Wert (ein Präfix) zuzuweisen, damit er im XPath-Ausdruck explizit ausgewählt werden kann. Der Standardnamespace ist nicht anders.
Denken Sie darüber nach: Ein Element in einem Namespace und ein anderes Element mit demselben Namen in einem anderen Namespace (oder überhaupt keinem Namespace) sind verschiedene -Elemente. Sie könnten verschiedene Dinge bedeuten (d. H. Darstellen). Das ist der springende Punkt. Sie müssen XPath mitteilen, welches Sie auswählen möchten. Ohne sie weiß XPath nicht, wonach Sie fragen.
Das Hinzufügen der Präfixe wird auf lange Sicht nicht bewältigt werden können.
Ich verstehe wirklich nicht warum. Was auch immer den XPath-Ausdruck erzeugt, sollte in der Lage sein, einen richtigen XPath-Ausdruck anzugeben (oder es ist ein fehlerhaftes Werkzeug).
Sie denken vielleicht: " Warum kann ich nicht einfach den Namespace ignorieren und alle Elemente erhalten, die mit diesem Namen übereinstimmen? " Es gibt wirklich hacky Wege, dies zu tun (wie die XSLT-basierte Antwort bereits) gepostet), aber sie sind gebrochen von Design. Ein Element in XML wird durch die Kombination von Namespace und lokalem Namen identifiziert, genauso wie Ihr Haus in einigen Städten und Staaten (der Namespace) mit einer Hausnummer (dem lokalen Namen) identifiziert werden kann. Wenn ich dir sage, dass ich auf 422 Main Street lebe, dann hast du immer noch keine Ahnung, wo ich lebe, bis ich dir sage, welche Stadt und Staat.
Sie denken vielleicht immer noch, " genug mit den dummen Analogien, ich möchte wirklich, wirklich das sowieso machen ." Sie können Elemente mit einem bestimmten Namen für alle Namespaces auswählen, indem Sie nur den lokalen Namensteil des Elements wie folgt abgleichen:
%Vor%Beachten Sie, dass sich dies nicht auf den Standardnamespace beschränkt. Es ignoriert Namespaces vollständig. Es ist hässlich und ich empfehle es nicht, aber manchmal wollen Sie einfach ignorieren, was am besten ist und etwas erledigen.
Das ist übrigens nicht die Schuld von PHP. Dies erfordert die XPath-Spezifikation. Sie müssen ein Präfix angeben, um einen Knoten in einem Namespace auszuwählen. Wenn PHP es Ihnen erlauben würde, es auf eine andere Art und Weise zu tun, dann wäre es, wie auch immer man es nannte, nicht mehr XPath (entsprechend der Spezifikation).
Um Hacks wie die str_replace
one zu vermeiden, die Sie dort haben (und ich würde das vermeiden), können Sie die XML-Dateien über eine XSLT ausführen, um den Namespace zu entfernen:
Wenn an einem dieser Eingänge ausgeführt wird:
%Vor%Die Ausgabe ist die gleiche:
%Vor%Damit können Sie Ihre Präfix-losen XPaths für das Ergebnis verwenden.
Tags und Links php namespaces xml xpath simplexml