XML-namespaces und XPath
Ich habe eine Anwendung, die zum laden von XML-Dokumenten-und output-Knoten je nach XPath.
Angenommen, ich beginne mit einem Dokument wie diesem:
<aaa>
...[many nodes here]...
<bbb>text</bbb>
...[many nodes here]...
<bbb>text</bbb>
...[many nodes here]...
</aaa>
Mit XPath //bbb
Soweit alles schön.
Und Auswahl doc.SelectNodes("//bbb");
liefert die Liste der benötigten Knoten.
Dann lädt jemand ein Dokument mit einem Knoten wie <myfancynamespace:foo/>
- und extra-namespace im Wurzel-tag, und alles bricht.
Warum? //bbb
nicht give a damn über myfancynamespace
, theoretisch sollte es auch gut sein mit //myfancynamespace:foo
, da gibt es keine Täuschung, sondern der Ausdruck gibt 0 zurück, Ergebnisse und das ist es.
Gibt es eine Abhilfe für dieses Verhalten?
Ich habe ein namespace-manager für das Dokument, und ich leite es an die Xpath-Abfrage. Aber die Namensräume und Präfixe sind mir unbekannt, also kann ich nicht fügen Sie Sie, bevor Sie die Abfrage.
Muss ich die pre-parse das Dokument zu füllen, die namespace-manager, bevor ich irgendeine Auswahl? Warum auf der Erde ein solches Verhalten, es macht einfach keinen Sinn.
EDIT:
Bin ich mit:
XmlDocument
und XmlNamespaceManager
EDIT2:
XmlDocument doc = new XmlDocument();
doc.XmlResolver = null;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
//I wish I could:
//nsmgr.AddNamespace("magic", "http://magicnamespaceuri/
//...
doc.LoadXML(usersuppliedxml);
XmlNodeList nodes = doc.SelectNodes(usersuppliedxpath, nsmgr);//usersuppliedxpath -> "//bbb"
//nodes.Count should be > 0, but with namespaced document they are 0
EDIT3:
Fand einen Artikel, der beschreibt das eigentliche Szenario das Problem mit einem workaround, aber nicht sehr hübsch Problemumgehung: http://codeclimber.net.nz/archive/2008/01/09/How-to-query-a-XPath-doc-that-has-a-default.aspx
Scheint fast, dass das "stripping" xmlns dem Weg zu gehen...
- Könntest du die relevanten Codezeilen? (Instanziierung XmlDocument, XPath, usw.)
- Ok, bearbeitet die post, siehe Edit2.
- Sie sagen, dass eine unerwartete Eingabe Ergebnisse in unerwartete Ausgabe für einen gegebenen Prozess. das ist der Anwendungsfall für die Validierung.
- "und extra-namespace im Wurzel-tag" - das ist schon fast unsinnig. Ich nehme an, du meinst, es gibt einen extra namespace-Deklaration im start-tag des äußersten element. Ist es ein Standard-namespace-Deklaration (
xmlns="..."
)? oder ist es eine Erklärung für myfancynamespace (xmlns:myfancynamespace="..."
)? Nur die ersteren betreffen würde, der dem Namensraum<bbb>
. Sie haben nicht gezeigt, was uns die Eingabe-XML aussieht, noch beschrieb es klar und deutlich, was es schwer macht zu erraten, was das problem ist. - Wenn ich sagte, 'Sie haben nicht gezeigt, was uns die XML-input-sieht aus wie' meinte ich die, die das problem verursacht.
- wenn Sie versuchen, speichern Sie die Benutzer einige Probleme, bitte nicht lehren Sie, dass der XPath-Ausdruck
//foo
übereinstimmen sollten, jedes element unabhängig von seinem Namensraum. Das wird nur dazu führen, Ihnen (und uns allen) noch mehr Probleme in die Zukunft. Wenn das eingabedokument Elemente in den falschen namespace-Dokument ist ungültig und sollte abgelehnt werden. Ihr Werkzeug wird Sie überzeugen, dass Ihr Dokument in Ordnung ist, und dann werden Sie alle mehr verwirrt, wenn Sie füttern Sie den nächsten downstream-Programm und es drosseln. - Dieses Q&A ist mein problem gelöst. Allerdings, bei der Suche, ich wusste nicht, dass der namespace wurde ein Konzept Schuld. Mein problem war, dass meine xpath-Suchvorgänge wurden ganz einfach die Rücksendung nichts.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihnen fehlt der ganze Sinn von XML-Namensräumen.
Aber wenn Sie wirklich brauchen, um ausführen von XPath-Dokumente verwenden, die einen unbekannten namespace, und Sie wirklich nicht kümmern, werden Sie brauchen, um Streifen Sie es aus und laden Sie das Dokument. XPath wird nicht funktionieren in einem namespace-unabhängige Weg, es sei denn, Sie verwenden möchten die
local-name()
Funktion an jedem Punkt Ihrer Selektoren.<myfancynamespace:foo/>
ist nicht unbedingt das gleiche wie<foo/>
.Namespaces nicht egal. Aber verstehen kann ich deinen Frust wie Sie in der Regel neigen dazu, Pausen-codes, wie verschiedene in der Implementierung (C#, Java, ...) sind in der Regel Ausgabe ist es anders.
Ich schlage vor, Sie ändern Ihren XPath-Ausdruck zu gestatten, für die Annahme aller namespaces. Zum Beispiel, anstatt
Definieren es als
Sollte sich darum kümmern.
local-name()
und Sie sollten in der Lage sein, um es in kurzer Zeit abholen.//NSURI:foo
syntax, woNSURI
ist ein namespace-URI. Wenn Sie versuchen, das zu unterstützen, verwenden//*[namespace-uri() = 'a:b:c']
. Das ist gültige XPath.foo
). Es ist verwirrend, dass diese unterschiedlich sein kann, aber wenn Sie denken über die Validierung von XML-Dokumenten aus vielen verschiedenen Quellen, werden Sie sehen, warum Sie müssen unterschiedlich sein.Sollten Sie beschreiben etwas Ausführlicher, was Sie tun möchten. Die Art und Weise Sie Ihre Frage es überhaupt keinen Sinn machen. Der namespace ist nur ein Teil des namens. Nichts mehr, nichts weniger. Also Ihre Frage ist die gleiche, wie zu Fragen, für eine XPath-Abfrage, um alle tags mit der Endung "x". Das ist nicht die Idee hinter XML, aber wenn man seltsame Gründe, dies zu tun: Fühlen Sie sich frei, um die Iteration über alle Knoten und es selbst implementieren. Das gleiche gilt für Funktionen, die Sie anfordern.
<myfancynamespace:foo/>
...bbb
element. Wenn Sie also die Standard-namespace der XPath-Umgebung, dann ignorieren die meisten von meinen vorherigen Kommentar.Könnten Sie die LINQ XML-Klassen wie
XDocument
. Sie vereinfachen die Arbeit mit namespaces.