首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用libxml++为XPath注册命名空间

使用libxml++为XPath注册命名空间
EN

Stack Overflow用户
提问于 2016-04-11 15:20:48
回答 2查看 1.3K关注 0票数 2

我用C++库编写了一个libxml++解析器,它构建在C libxml2库上。当xmlns不存在于xml中时,它工作得很好,但是当添加了名称空间时,它就会中断。

示例xml:

代码语言:javascript
运行
复制
<A xmlns="http://some.url/something">
  <B>
    <C>hello world</C>
  <B>
</a>

样本XPath:

代码语言:javascript
运行
复制
string xpath = "/A/B/C" // returns nothing when xmlns is present in the XML

我找到了这个答案,并尝试将我的XPath调整到以下几个方面,这确实有效,但它使XPath读和写起来有点讨厌。

代码语言:javascript
运行
复制
string xpath = "/*[name()='A']/*[name()='B']/*[name()='C']"

理想情况下,我希望注册名称空间,这样我就可以使用普通的XPaths。我还搜索了libxml++文档并找到了一个Node.set_namespace,但是当我尝试使用它时,它只会导致异常。

代码语言:javascript
运行
复制
root_node->set_namespace("http://some.url/something");
// exception: The namespace (http://some.url/something) has not been declared.

但是,root_node在解析XML文档时绝对知道名称空间:

代码语言:javascript
运行
复制
cout << "namespace uri: " << root_node->get_namespace_uri();
// namespace uri: http://some.url/something

在这一点上,我没有想法,所以帮助是非常感谢的。

编辑也尝试过:

代码语言:javascript
运行
复制
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: 

没有抱怨,但似乎没有注册名称空间。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-11 18:15:27

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

对于libxml2,请看一下xmlXPathRegisterNs

与包装器一样,隐藏的复杂性甚至(很可能是)功能。

查看一下libxml++源代码就会发现,存在使用xmlXPathRegisterNs的find重载。

代码语言:javascript
运行
复制
using PrefixNsMap = std::map<Glib::ustring, Glib::ustring>
NodeSet find(const Glib::ustring& xpath, const PrefixNsMap& namespaces);

为此,尝试用PrefixNsMap调用find,并以前缀作为键。

更新:

代码语言:javascript
运行
复制
 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;

对有关名称空间的奇怪讨论的评论:

  • 在xml文档中经常使用默认命名空间。
  • xml文档中的默认命名空间可以在任何节点中更改,并且在下一次更改之前有效。
  • 带前缀的命名空间仅对具有此前缀的节点有效。
  • 从xpath的角度来看,xml中使用的前缀并不重要。您需要知道在wich名称空间(uri)中节点是什么。每个名称空间都需要注册,以便在xpaht中使用唯一的名称空间前缀。
  • 避免使用这个*[name()='A']或*本地名称()=‘A’的东西。
票数 3
EN

Stack Overflow用户

发布于 2016-04-11 18:15:38

当您为xmlns使用前缀时,我相信您的xml应该是:

代码语言:javascript
运行
复制
<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‘。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36552800

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档