代码之家  ›  专栏  ›  技术社区  ›  joshk0

libxml2中奇怪的xpath行为

  •  2
  • joshk0  · 技术社区  · 15 年前

    我有一个这样的XML树(我已经更改了标记名,但是如果你真的很聪明,你可以知道我在做什么。)

    <ListOfThings>
       <Thing foo:action="add">
          <Bar>doStuff --slowly</Bar>
          <Index>1</Index>
       </Thing>
       <Thing foo:action="add">
          <Bar>ping yourMother.net</Bar>
          <Index>2</Index>
       </Thing>
    </ListOfThings>
    

    使用libxml2,我希望以编程方式将一个新的thing标记插入到其中,其中索引是当前最高的索引,加上一个。我是这样做的(为了简洁起见删除了健全性检查):

    xpath = "//urn:myformat[@foo='bar']/"
            "urn:mysection[@name='baz']/"
            "urn:ListOfThings/urn:Thing/urn:Index";
    
    xpathObj = xmlXPathEvalExpression(xpath, xpathCtx);
    nodes = xpathObj->nodesetval;
    
    /* Find last value and snarf the value of the tag */
    highest = atoi(nodes->nodeTab[nodes->nodeNr - 1]->children->content);
    snprintf(order, sizeof(order), "%d", highest + 1); /* highest index plus one */
    
    /* now move up two levels.. */
    cmdRoot = nodes->nodeTab[nodes->nodeNr - 1];
    ASSERT(cmdRoot->parent && cmdRoot->parent->parent);
    cmdRoot = cmdRoot->parent->parent;
    
    /* build the child tag */
    newTag = xmlNewNode(NULL, "Thing");
    xmlSetProp(newTag, "foo:action", "add");
    
    /* set new node values */
    xmlNewTextChild(newTag, NULL, "Bar", command);
    xmlNewChild(newTag, NULL, "Index", order);
    
    /* append this to cmdRoot */
    xmlAddChild(cmdRoot, newTag);
    

    但是如果我调用这个函数两次(添加两件事),xpath表达式就不会捕获我所做的新条目。我是否需要调用一个函数来激发胫骨中的xpath,并获取它以确保它再次检查整个xmldocptr?很明显,它会被添加到文档中,因为当我保存它时,会得到我添加的新标签。

    显然,输出如下所示:

    <ListOfThings>
       <Thing foo:action="add">
          <Bar>doStuff --slowly</Bar>
          <Index>1</Index>
       </Thing>
       <Thing foo:action="add">
          <Bar>ping yourMother.net</Bar>
          <Index>2</Index>
       </Thing>
       <Thing foo:action="add">
          <Bar>newCommand1</Bar>
          <Index>3</Index>
       </Thing>
       <Thing foo:action="add">
          <Bar>newCommand2</Bar>
          <Index>3</Index> <!-- this is WRONG! -->
       </Thing>
    </ListOfThings>
    

    我用了一个调试器来检查调用xmlxpathevalexpression之后发生了什么,我看到了 nodes->nodeNr 每次都是一样的。

    救救我,LazyWeb,你是我唯一的希望!

    1 回复  |  直到 15 年前
        1
  •  2
  •   Rob Richards    15 年前

    基于您的xpath,它看起来像是一个名称空间文档的片段(使用默认名称空间)。我敢打赌,您以前调用过将“urn”注册为使用xmlxpathregisterns的名称空间的前缀。添加新节点时,不会在名称空间中创建它们,因此xpath只能正确地选择名称空间的“index”元素。