我用C++库编写了一个libxml++解析器,它构建在C libxml2库上。当xmlns
不存在于xml中时,它工作得很好,但是当添加了名称空间时,它就会中断。
示例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读和写起来有点讨厌。
string xpath = "/*[name()='A']/*[name()='B']/*[name()='C']"
理想情况下,我希望注册名称空间,这样我就可以使用普通的XPaths。我还搜索了libxml++文档并找到了一个Node.set_namespace
,但是当我尝试使用它时,它只会导致异常。
root_node->set_namespace("http://some.url/something");
// exception: The namespace (http://some.url/something) has not been declared.
但是,root_node
在解析XML文档时绝对知道名称空间:
cout << "namespace uri: " << root_node->get_namespace_uri();
// namespace uri: http://some.url/something
在这一点上,我没有想法,所以帮助是非常感谢的。
编辑也尝试过:
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:
没有抱怨,但似乎没有注册名称空间。
发布于 2016-04-11 18:15:27
libxml++的在线文档没有提到如何在xpaht表达式中使用名称空间。但是正如您所指出的,libxml++是libxml2的包装器。
对于libxml2,请看一下xmlXPathRegisterNs。
与包装器一样,隐藏的复杂性甚至(很可能是)功能。
查看一下libxml++源代码就会发现,存在使用xmlXPathRegisterNs的find重载。
using PrefixNsMap = std::map<Glib::ustring, Glib::ustring>
NodeSet find(const Glib::ustring& xpath, const PrefixNsMap& namespaces);
为此,尝试用PrefixNsMap调用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;
对有关名称空间的奇怪讨论的评论:
*[name()='A']
或*本地名称()=‘A’的东西。发布于 2016-04-11 18:15:38
当您为xmlns使用前缀时,我相信您的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
‘。
https://stackoverflow.com/questions/36552800
复制相似问题