如何通过xmlXPathNodeEval()将XPath限制为子树? [英] How to restrict an XPath via xmlXPathNodeEval() to a subtree?

查看:66
本文介绍了如何通过xmlXPathNodeEval()将XPath限制为子树?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要仅在某个子树内评估XPath表达式,libxml2函数xmlXPathNodeEval()似乎是可行的方法. 文档指定 XPath表达式是在给定上下文"中求值的.但这到底是什么意思?

To evaluate an XPath expression only inside a certain subtree the libxml2 function xmlXPathNodeEval() seems to be the way to go. The documentation specifies that the XPath expression is evaluated 'in the given context'. But what does this exactly mean?

考虑以下小示例:

#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xmlstring.h>
#include <stdio.h>
int main(int argc, char **argv)
{
  const char inp[] =
    "<root>\n"
    " <sub>\n"
    "  <e>0</e>\n"
    "  <Foo>\n"
    "    <e>1</e><e>2</e><e>3</e>\n"
    "    <FooSub><e>3a</e></FooSub>\n"
    "  </Foo>\n"
    "  <Bar>\n"
    "    <e>4</e><e>5</e><e>6</e>\n"
    "  </Bar>\n"
    " </sub>\n"
    " <e>7</e>\n"
    "</root>\n";
  xmlDoc *doc = xmlParseMemory(inp, sizeof(inp)-1);
  xmlXPathContext *ctx = xmlXPathNewContext(doc);
  xmlXPathObject *p = xmlXPathEval(BAD_CAST "//Foo[1]", ctx);

  xmlNode *new_root = *p->nodesetval->nodeTab;
  printf("New root: %s\n", BAD_CAST new_root->name);
  xmlXPathObject *q = xmlXPathNodeEval(new_root, BAD_CAST argv[1], ctx);

  for (int i = 0; i<q->nodesetval->nodeNr; ++i) {
    const xmlChar *cnt = xmlNodeGetContent(q->nodesetval->nodeTab[i]);
    printf("%s ", BAD_CAST cnt);
    xmlFree((xmlChar*)cnt);
  }
  puts("");

  xmlXPathFreeObject(q);
  xmlXPathFreeObject(p);
  xmlXPathFreeContext(ctx);
  xmlFreeDoc(doc);
  return 0;
}

通过(在我的情况下,使用2.9.1版本的libxml编译):

Compiled via (in my case using version 2.9.1 of libxml):

$ gcc -g -std=c99 -Wall -I/usr/include/libxml2 -lxml2 relative.c

通话

$ ./a.out '//e'

我希望得到以下输出:


New root: Foo
1 2 3 3a

但是我得到了:


New root: Foo
0 1 2 3 3a 4 5 6 7

似乎我必须使用self::node()轴说明符(简称.)来获得所需的结果,即:

It seems that I have to use the self::node() axis specifier (short .) to get the result I want, i.e.:

$ ./a.out './/e'
New root: Foo
1 2 3 3a 

基本上,我从文档中将句子评估给定上下文中的XPath位置路径"解释为:XPath表达式是在给定节点的self::node()上下文中求值的-但由于必须显式指定事实并非如此.

Basically I was interpreting the sentence 'Evaluate the XPath Location Path in the given context' from the documentation as: the XPath expression is evaluated in the self::node() context at that given node - but since one has to explicitly specify self::node() this is not the case.

因此,一个相关的问题也许是:libxml2的行为及其对术语上下文"的使用是否与XPath规范一致?

Thus, a related question is perhaps: is the behavior of libxml2 and its usage of the term 'context' consistent to the XPath specification?

推荐答案

XPath选择输入树中的节点,以斜杠/开头的路径从上下文节点的文档节点向下选择节点.因此,如已正确发现,如果要选择相对于上下文节点的后代,则需要.//foo.或者,您可以使用descendant::foo.

XPath selects nodes in an input tree and a path starting with the slash / selects nodes downwards from the document node of the context node. So as you have found out correctly, if you want to select descendants relative to your context node, you need .//foo. As an alternative, you can use descendant::foo.

这篇关于如何通过xmlXPathNodeEval()将XPath限制为子树?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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