使用 libxml++ 为 XPath 注册命名空间 [英] Register namespace with libxml++ for XPath

查看:16
本文介绍了使用 libxml++ 为 XPath 注册命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I wrote a C++ XPath parser with the libxml++ library, which was built on the C libxml2 library. It works great when the xmlns is not present in xml but it breaks when that namespace is added.

示例 xml:

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

示例 XPath:

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

我找到了 这个答案 并尝试将我的 XPath 调整为以下内容,这确实有效,但它使 XPath 有点像讨厌阅读和写作.

I found this answer and tried adjusting my XPath to the following, which does work but it makes the XPath kind of obnoxious to read and write.

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

理想情况下,我想注册命名空间,以便我可以使用普通的 XPath.我还搜索了 libxml++ 文档并找到了一个 Node.set_namespace 但它只是在我尝试使用它时导致异常.

Ideally I want to register the namespace so I can use normal XPaths. I've also searched through the libxml++ documentation and found a Node.set_namespace but it just causes an exception when I try to use it.

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

然而,root_node 在解析 XML 文档时肯定知道命名空间:

However, the root_node is definitely aware of the namespace when it parses the XML document:

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

此时我没有想法,非常感谢帮助.

At this point I am out of ideas so help is greatly appreciated.

编辑也试过:

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: 

没有抱怨但似乎没有注册命名空间.

Does not complain but doesn't appear to register the namespace.

推荐答案

libxml++ 的在线文档没有提到如何使用带有 xpaht 表达式的命名空间.但是正如您指出的那样,libxml++ 是 libxml2 的包装器.

The online documentation for libxml++ does not mention how to use namespaces with xpaht expression. But as you pointed out libxml++ is a wrapper to libxml2.

对于 libxml2,请查看 xmlXPathRegisterNs.

For libxml2 have a look to xmlXPathRegisterNs.

与包装器一样,隐藏复杂性甚至(最有可能的)功能.

As always with wrapper the hide complexity and even (most likely) functionality.

查看 libxml++ 源代码表明存在使用 xmlXPathRegisterNs 的查找重载.

Having a look to the libxml++ sourcecode shows that there are find overloads which make use of xmlXPathRegisterNs.

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

因此尝试使用 PrefixNsMap 调用 find,以前缀为键.
更新:

Therefor try to call find with the PrefixNsMap, with the prefix as key.
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;

评论关于命名空间的奇怪讨论:

Comment to strange discussion about namespaces:

  • xml 文档中经常使用默认命名空间
  • xml 文档中的默认命名空间可以在任何节点中更改,并且在下一次更改之前一直有效.
  • 带有前缀的命名空间仅对带有此前缀的节点有效.
  • 从 xpath 的角度来看,xml 中使用的前缀并不重要.您需要知道节点所在的命名空间(uri).每个命名空间都需要注册以在 xpaht 中使用唯一的命名空间前缀.
  • 避免使用此 *[name()='A']*[local-name()='A']`东西.
  • A default namespace is often used in xml documents
  • The default namespace in a xml document could be changed in any node and is valid until the next change.
  • A namespace with prefix is only valid for nodes with this prefix.
  • Form xpath point of view the used prefix in xml does not really matter. You need to know in wich namesapace (uri) the nodes are. Each namespace need to be register for use in xpaht with an unique namespace prefix.
  • Avoid using this *[name()='A'] or *[local-name()='A']`stuff.

这篇关于使用 libxml++ 为 XPath 注册命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆