6

我正在使用 Libxml2 将数据编码到 xml 文件中。我的数据包含“<”和“>”之类的标签。当它被转换成 xml 时,这些标签也被转换成“<”和“>”。有什么办法可以解决这个问题。我想在解码那个 xml 文件时使用这些标签作为 xml 节点,所以 CDATA 不是这个问题的解决方案。请为此提供任何解决方案。谢谢。

示例代码:

xmlNewChild(node, NULL, (xmlChar *)"ADDRESS", (xmlChar *)"<street>Park Street</street><city>kolkata</city>");

and output of above code is:
<person>
<ADDRESS>&lt;street&gt;Park Street&lt;/street&gt;&lt;city&gt;Kolkata&lt;/city&gt;</ADDRESS>
4

4 回答 4

3

如果要将字符串视为 xml,则应xmlDoc使用xmlReadMemory对其进行解析并从中获取。它可以用于更大的字符串,但通常文档是使用单步指令构建的,就像在 Joachim 的回答中一样。在这里,我介绍xmlAddChildFromString了以字符串方式执行这些操作的函数。

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

/// Returns 0 on failure, 1 otherwise
int xmlAddChildFromString(xmlNodePtr parent, xmlChar *newNodeStr)
{
  int rv = 0;
  xmlChar *newNodeStrWrapped = calloc(strlen(newNodeStr) + 10, 1);
  if (!newNodeStrWrapped) return 0;
  strcat(newNodeStrWrapped, "<a>");
  strcat(newNodeStrWrapped, newNodeStr);
  strcat(newNodeStrWrapped, "</a>");
  xmlDocPtr newDoc = xmlReadMemory(
    newNodeStrWrapped, strlen(newNodeStrWrapped),
    NULL, NULL, 0);
  free(newNodeStrWrapped);
  if (!newDoc) return 0;
  xmlNodePtr newNode = xmlDocCopyNode(
    xmlDocGetRootElement(newDoc),
    parent->doc,
    1);
  xmlFreeDoc(newDoc);
  if (!newNode) return 0;
  xmlNodePtr addedNode = xmlAddChildList(parent, newNode->children);
  if (!addedNode) {
    xmlFreeNode(newNode);
    return 0;
  }
  newNode->children = NULL; // Thanks to milaniez
  newNode->last = NULL;     // for fixing
  xmlFreeNode(newNode);     // the memory leak.
  return 1;
}

int
main(int argc, char **argv)
{
    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
    xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "root");
    xmlDocSetRootElement(doc, root);
    xmlAddChildFromString(root,
      "<street>Park Street</street><city>kolkata</city>");
    xmlDocDump(stdout, doc);
    xmlFreeDoc(doc);
    return(0);
}
于 2012-10-17T06:47:54.267 回答
2

您必须调用xmlNewChild一个链,一个调用父节点,一个调用每个子节点:

xmlNodePtr *addressNode = xmlNewChild(node, NULL, (xmlChar *) "address", NULL);
xmlNewChild(addressNode, NULL, (xmlChar *) "street", "Park Street");
xmlNewChild(addressNode, NULL, (xmlChar *) "city", "Koltaka");
于 2012-10-17T06:42:50.653 回答
2

您可以尝试使用函数 xmlParseInNodeContext。它允许您在父节点的上下文中解析原始 XML,并构造一个可以附加到父节点的节点。

例如:

const char * xml = "<a><b><c>blah</c></b></a>";
xmlNodePtr new_node = NULL;

// we assume that 'parent' node is already defined
xmlParseInNodeContext(parent, xml, strlen(xml), 0, &new_node);
if (new_node) xmlAddChild(parent, new_node);
于 2013-10-17T23:54:56.120 回答
1

我现在使用以下代码将 XML 文本(可能包含多个元素)注入现有节点(感谢 Nazar 和 nwellnhof 提供的唯一答案并从我的问题中引用我(Injecting a string into an XML node without content escaping)到这个):

std::string xml = "<a>" + str + "</a>";
xmlNodePtr pNewNode = nullptr;
xmlParseInNodeContext(pParentNode, xml.c_str(), (int)xml.length(), 0, &pNewNode);
if (pNewNode != nullptr)
{
    // add new xml node children to parent
    xmlNode *pChild = pNewNode->children;
    while (pChild != nullptr)
    {
        xmlAddChild(pParentNode, xmlCopyNode(pChild, 1));
        pChild = pChild->next;
    }

    xmlFreeNode(pNewNode);
}

它需要字符串 (str) 添加一个环绕元素 (< a >...< a/ >),使用xmlParseInNodeContext解析字符串,然后将新节点的子节点添加到父节点。重要的是添加新节点的子节点而不是新节点,以避免在最终 XML 中出现 <a>...<a/ >。

于 2014-03-04T13:55:15.640 回答