使用libxml+注册名称空间+;对于XPath 我用C++在库中建立了一个C++ XPath解析器。当xml中不存在xmlns时,它工作得很好,但当添加名称空间时,它会中断

使用libxml+注册名称空间+;对于XPath 我用C++在库中建立了一个C++ XPath解析器。当xml中不存在xmlns时,它工作得很好,但当添加名称空间时,它会中断,c++,xml,xpath,C++,Xml,Xpath,示例xml: <A xmlns="http://some.url/something"> <B> <C>hello world</C> <B> </a> 我发现并尝试将我的XPath调整为以下内容,这确实有效,但它使XPath读写起来有点讨厌 string xpath = "/*[name()='A']/*[name()='B']/*[name()='C']" 理想情况下,我希望注册名称空间,以便可以使用

示例xml:

<A xmlns="http://some.url/something">
  <B>
    <C>hello world</C>
  <B>
</a>
我发现并尝试将我的XPath调整为以下内容,这确实有效,但它使XPath读写起来有点讨厌

string xpath = "/*[name()='A']/*[name()='B']/*[name()='C']"
理想情况下,我希望注册名称空间,以便可以使用普通XPath。我还搜索了libxml++文档,发现了一个异常,但当我尝试使用它时,它只会导致一个异常

root_node->set_namespace("http://some.url/something");
// exception: The namespace (http://some.url/something) has not been declared.
但是,
根节点在解析XML文档时肯定知道名称空间:

cout << "namespace uri: " << root_node->get_namespace_uri();
// namespace uri: http://some.url/something
cout-get_-document()->get_-root_-node();
根节点->设置名称空间声明(“http://some.url/something“,“x”);

coutlibxml++的在线文档没有提到如何将名称空间与xpaht表达式一起使用。 但正如您所指出的,libxml++是libxml2的包装器

对于libxml2,请查看

和往常一样,包装器隐藏了复杂性,甚至(很可能)功能

查看libxml++源代码可以发现有一些使用xmlXPathRegisterNs的find重载

using PrefixNsMap = std::map<Glib::ustring, Glib::ustring>
NodeSet find(const Glib::ustring& xpath, const PrefixNsMap& namespaces);
使用前缀nsmap=std::map
节点集查找(const Glib::ustring和xpath、const PrefixNsMap和名称空间);
因此,请尝试使用前缀NSMAP调用find,前缀作为键。
更新:

 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;
xmlpp::Node::PrefixNsMap;
nsmap[“x”]=“http://some.url/something";
自动设置=节点->查找(xpath、nsmap);

std::cout当您为XMLN使用前缀时,我认为您的xml应该是:

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

你好,世界

xpath表达式
/x:A/x:B/x:C/text()
将产生“
hello world

我认为您需要使用:void xmlpp::Element::set_namespace_声明(const std::string&ns_uri,const std::string&ns_prefix=std::string())定义良好我的变量是
节点
,但是
元素
节点
的子元素,所以我可以让它工作。我会尝试一下。节点类型可以是元素节点类型,实际上这里“a”是我假定的元素节点。我的代码很高兴
根节点
元素
,我调用
根节点->设置命名空间声明(“http://some.url/something“,“x”)。这没有问题,但当我尝试计算XPath
“”/x:A/x:B/x:C时“
我收到这个错误
XPath错误:未定义的命名空间前缀
。有什么想法吗?我尝试在我的
set\u namespace\u声明
调用中反转参数,以防出现错误,但没有成功。请查看
xmlXPathRegisterNs
抱歉,这似乎是错误的。请看一下默认名称空间。如果用户希望使用非默认的xml名称空间,请解释为什么这是错误的?看一看:使用前缀是有原因的,以避免名称冲突这里没有
x
是namespce前缀和
http://some.url/something
名称空间。prfix可以为空。那么,对于所有没有前缀的元素,都有一个dedault名称空间。在这种情况下,如何确保元素属于该名称空间?是否希望所有元素都引用该默认命名空间?例如,我有另一个同名的元素B,我不希望它在该名称空间下查看,但在另一个名称空间下查看xpath/A/B/C会得到什么?这似乎很有帮助,因为当我运行问题中的代码时,它会打印出
“名称空间前缀:x”
。所以libxml++肯定理解它。但有两个问题1)我无法更改XML发送给我的方式,因此我必须添加“x:”如果这样做有效的话,将有数百万个文本行;2)由于某种原因,当我尝试运行XPath时,我奇怪地仍然得到
XPath错误:未定义的名称空间前缀
。谢谢,但我不确定在不添加下载源代码、实现它并重新编译库的情况下如何从libxml++调用它。谢谢!我目前使用的是libxml++2.6,但我可以将其升级到3.0。我会尝试一下,然后再报告。你用2.6试过了吗。我没有,所以我不知道这是否也会起作用还没有,但我会尝试一下,然后再报告,虽然今天可能没有时间。@Mike,你有什么反应/结果吗?
 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;
<x:A xmlns:x="http://some.url/something">
  <x:B>
    <x:C>hello world</x:C>
  </x:B>
</x:A>