libmxl2 - 改变元素的值,混合内容

libmxl2 - change value of element, with mixed content

我正在为使用 libxml2 库做一些小包装。如果它包含混合内容,则更改元素值会出现问题。

在下面的示例中,我正在创建 "child1" 元素,其值为 "OLD CONTENT" 并带有子元素 "child1.1"。然后我尝试使用 xmlNodeSetContent 函数(标有 <--- 的行)将 "child1" 值更改为 "NEW CONTENT"。问题是,"child1.1" 被 xmlNodeSetContent 删除了。我只想将值从 "OLD CONTENT" 更改为 "NEW CONTENT"。

似乎 xmlNodeSetContent 不是执行此操作的正确函数,或者 libxml2 中可能还有其他我缺少的东西。

问题:有没有办法在混合内容的情况下更改值?如果可以,该怎么做?

#include <stdio.h>
#include <string.h>

#include <libxml/parser.h>
#include <libxml/tree.h>

#define MY_ENCODING "ISO-8859-1"

xmlNodePtr createRoot(xmlDocPtr doc, char* name)
{
    xmlNodePtr root;
    root = xmlNewNode(NULL, BAD_CAST name);
    xmlDocSetRootElement(doc, root);
    return root;
}

xmlNodePtr addChild(xmlNodePtr parent, char* name, char* value)
{
    return xmlNewChild(parent, NULL, BAD_CAST name, BAD_CAST value);
}

void setElementContent(xmlNodePtr element, char* value)
{
    xmlNodeSetContent(element, BAD_CAST value);
}

void setElementAttribute(xmlNodePtr element, char* attribName, char* attribValue)
{
    xmlSetProp(element, BAD_CAST attribName, BAD_CAST attribValue);
}

int main(int argc, char** argv)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr root = NULL;
    xmlNodePtr tmp1 = NULL;
    xmlNodePtr tmp11 = NULL;
    xmlNodePtr tmp2 = NULL;

    xmlChar* xmlbuff;
    int buffersize;


    doc = xmlNewDoc(BAD_CAST "1.0");

    root = createRoot(doc, "root");

    //tmp1 = addChild(root, "child1", NULL);
    tmp1 = addChild(root, "child1", "OLD CONTENT");

    tmp11 = addChild(tmp1, "child1.1", NULL);
    setElementContent(tmp11, "blablabla");

    tmp2 = addChild(root, "child2", NULL);
    setElementContent(tmp2, "22222");
    setElementAttribute(tmp2, "id", "002");
    setElementAttribute(tmp2, "lang", "en");

    setElementContent(tmp1, "NEW CONTENT");   // <---

    //xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
    xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, MY_ENCODING, 1);
    printf("%s", (char *) xmlbuff);

    xmlCleanupParser();

    xmlFree(xmlbuff);
    xmlFreeDoc(doc);

    return 0;
}

编辑: 工作版本:

#include <stdio.h>
#include <string.h>

#include <libxml/parser.h>
#include <libxml/tree.h>

#define MY_ENCODING "ISO-8859-1"

xmlNodePtr createRoot(xmlDocPtr doc, char* name)
{
    xmlNodePtr root;
    root = xmlNewNode(NULL, BAD_CAST name);
    xmlDocSetRootElement(doc, root);
    return root;
}

xmlNodePtr addChild(xmlNodePtr parent, char* name, char* value)
{
    return xmlNewChild(parent, NULL, BAD_CAST name, BAD_CAST value);
}

void setElementContent(xmlNodePtr element, char* value)
{
    xmlNodePtr it = NULL;
    int bFound = 0;

    for (it = element->children; it != NULL; it = it->next)
    {
        if (it->type == XML_TEXT_NODE)
        {
            xmlNodeSetContent(it, BAD_CAST value);
            bFound = 1;
        }
    }

    if (!bFound)
    {
        xmlNodeSetContent(element, BAD_CAST value);
    }
}

void setElementAttribute(xmlNodePtr element, char* attribName, char* attribValue)
{
    xmlSetProp(element, BAD_CAST attribName, BAD_CAST attribValue);
}

void printXml(xmlDocPtr doc)
{
    xmlChar* xmlbuff;
    int buffersize;

    //xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
    xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, MY_ENCODING, 1);
    printf("%s", (char *) xmlbuff);
    xmlCleanupParser();
    xmlFree(xmlbuff);
}

int main(int argc, char** argv)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr root = NULL;
    xmlNodePtr tmp1 = NULL;
    xmlNodePtr tmp11 = NULL;
    xmlNodePtr tmp2 = NULL;
    xmlNodePtr tmp3 = NULL;
    xmlNodePtr it = NULL;

    doc = xmlNewDoc(BAD_CAST "1.0");

    root = createRoot(doc, "root");

    //tmp1 = addChild(root, "child1", NULL);
    tmp1 = addChild(root, "child1", "OLD CONTENT");

    tmp11 = addChild(tmp1, "child1.1", NULL);
    setElementContent(tmp11, "blablabla");

    tmp2 = addChild(root, "child2", NULL);
    setElementContent(tmp2, "22222");
    setElementAttribute(tmp2, "id", "002");
    setElementAttribute(tmp2, "lang", "en");

    tmp3 = addChild(root, "child3", NULL); /* create empty */

    printf("\nBefore:\n");
    printXml(doc);

    setElementContent(tmp1, "NEW CONTENT");
    setElementContent(tmp3, "333");

    printf("\nAfter:\n");
    printXml(doc);

    xmlFreeDoc(doc);

    return 0;
}

混合内容由一系列文本节点和元素节点表示。您必须检索文本节点并仅替换它的内容:

xmlNodePtr textNode = &tmp1->children[0];
setElementContent(textNode, "NEW CONTENT");
//setElementContent(tmp1, "NEW CONTENT");   // <---