2016-04-11 9 views
1

Ich schrieb einen C++ - XPath-Parser mit der libxml++-Bibliothek, die auf der C libxml2-Bibliothek erstellt wurde. Es funktioniert gut, wenn die xmlns nicht in Xml vorhanden ist, aber es bricht, wenn dieser Namespace hinzugefügt wird.Namespace registrieren mit libxml ++ für XPath

Probe xml:

<A xmlns="http://some.url/something"> 
    <B> 
    <C>hello world</C> 
    <B> 
</a> 

Probe XPath:

string xpath = "/A/B/C" // returns nothing when xmlns is present in the XML 

ich this answer gefunden und versucht, meine XPath auf die folgende Einstellung, die Arbeit tut, aber es macht die XPath Art unausstehlich zu lesen und schreiben.

string xpath = "/*[name()='A']/*[name()='B']/*[name()='C']" 

Idealerweise möchte ich den Namespace registrieren, damit ich normale XPaths verwenden kann. Ich habe auch die libxml ++ Dokumentation durchsucht und eine Node.set_namespace gefunden, aber es verursacht nur eine Ausnahme, wenn ich versuche, es zu verwenden.

root_node->set_namespace("http://some.url/something"); 
// exception: The namespace (http://some.url/something) has not been declared. 

jedoch die root_node ist auf jeden Fall bewusst, den Namespace, wenn es das Dokument XML analysiert:

cout << "namespace uri: " << root_node->get_namespace_uri(); 
// namespace uri: http://some.url/something 

An dieser Stelle ich aus Ideen bin so ist Hilfe sehr geschätzt.

EDIT auch versucht:

Element *root_node = parser->get_document()->get_root_node(); 
root_node->set_namespace_declaration("http://some.url/something","x"); 
cout << "namespace uri: " << root_node->get_namespace_uri() << endl; 
cout << "namespace prefix: " << root_node->get_namespace_prefix() << endl; 
// namespace uri: http://some.url/something 
// namespace prefix: 

beschwert sich nicht, aber scheint nicht den Namespace zu registrieren.

+0

Ich glaube, Sie verwenden müssen: Leere xmlpp :: Element :: set_namespace_declaration \t (\t) const std :: string & \t ns_uri, const std :: zeichenfolge & \t ns_prefix = std :: string() ) definiert [hier] (http://libxmlplusplus.sourceforge.net/docs/reference/1.0/html/classxmlpp_1_1Element.html#a2) – SomeDude

+0

Nun, meine Variable ist ein 'Node', aber' Element' ist ein Kind von ' Node', damit ich es schaffen kann. Ich werde es versuchen. –

+0

Knotentyp kann Element Knotentyp sein und infact hier 'A' ist ein Element Knoten ich vermute. – SomeDude

Antwort

0

Die Online-Dokumentation für libxml ++ erwähnt nicht, wie Namespaces mit Xpaht-Ausdruck verwendet werden. Aber wie Sie darauf hingewiesen haben, ist libxml ++ ein Wrapper für libxml2.

Für libxml2 werfen Sie einen Blick auf xmlXPathRegisterNs.

Wie immer mit Wrapper die Komplexität verbergen und sogar (wahrscheinlich) Funktionalität.

Ein Blick auf den libxml ++ - Quellcode zeigt, dass es Überladungen gibt, die xmlXPathRegisterNs verwenden.

using PrefixNsMap = std::map<Glib::ustring, Glib::ustring> 
NodeSet find(const Glib::ustring& xpath, const PrefixNsMap& namespaces); 

Daher versuchen, mit der PrefixNsMap, mit dem Präfix als Schlüssel suchen.
Update:

xmlpp::Node::PrefixNsMap nsmap; 
nsmap["x"] = "http://some.url/something"; 
auto set = node->find(xpath, nsmap); 
std::cout << set.size() << " nodes have been found:" << std::endl; 

Kommentar zu seltsamer Diskussion über Namespaces:

oft
  • Ein Standard-Namespace in XML-Dokumenten verwendet wird
  • Das Standard-Namespace in einem XML-Dokument in einem beliebigen Knoten geändert werden könnten und gilt bis zur nächsten Änderung.
  • Ein Namespace mit Präfix ist nur für Knoten mit diesem Präfix gültig.
  • Form xpath Blickwinkel das verwendete Präfix in xml ist nicht wirklich wichtig. Sie müssen wissen, in welchem ​​Namensraum (uri) die Knoten sind.Jeder Namespace muss für die Verwendung in xpaht mit einem eindeutigen Namespacepräfix registriert sein.
  • Vermeiden Sie die Verwendung dieser *[name()='A'] oder * [local-name() = 'A'] `Zeug.
+0

Danke, aber ich bin mir nicht sicher, wie ich das von libxml ++ nennen würde, ohne das Herunterladen des Quellcodes, implementieren, und kompilieren der Bibliothek –

+0

@Mike: Schauen Sie sich das Update an –

+0

@Mike: Mit libxml ++ 3.0 funktioniert das, –

-1

Wenn Sie Präfix für Ihre xmlns Ich glaube, Ihr xml sein sollte:

<x:A xmlns:x="http://some.url/something"> 
    <x:B> 
    <x:C>hello world</x:C> 
    </x:B> 
</x:A> 

und der XPath-Ausdruck /x:A/x:B/x:C/text() ergäbe 'hello world'

+0

Sorry, das scheint falsch zu sein. Sehen Sie sich den Standard-Namespace an. –

+0

Könnten Sie bitte erklären, warum dies falsch ist, wenn der Benutzer einen XML-Namespace verwenden möchte, der nicht standardmäßig ist? Werfen Sie einen Blick auf: http://www.w3schools.com/xml/xml_namespaces.asp Es gibt einen Grund, warum Präfixe verwendet werden, um Namenskonflikte zu vermeiden – SomeDude

+0

Kein 'x' ist hier das Namespce-Präfix und' http: // etwas .url/etwas "der Namensraum. Das Prfix kann leer sein. Dann haben Sie einen dedault-Namespace für alle Elemente ohne Präfix. –

Verwandte Themen