如何从带命名空间的字符串构建libxml2的xmlNode?
解决libxml2
xmlParseBalancedChunkMemory 命名空间前缀解析报错问题 问题根源
xmlParseBalancedChunkMemory 是独立解析XML片段的函数,不会自动继承目标文档中已有的命名空间上下文。哪怕你的doc已经定义了ds这类命名空间,解析片段时函数只会检查当前片段内的命名空间声明,找不到就抛出XML_NS_ERR_UNDEFINED_NAMESPACE(错误201)。
正确解析方式
方式一:给解析上下文绑定已有命名空间
手动把文档中已有的命名空间注入到解析上下文里,让函数能识别前缀对应的命名空间:
// 假设doc是已初始化且包含ds命名空间的xmlDocPtr xmlNsPtr ds_ns = xmlSearchNs(doc, doc->children, "ds"); if (!ds_ns) { // 处理命名空间未定义的异常 } // 创建解析上下文 xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); if (!ctxt) { // 内存分配失败处理 } // 将目标命名空间加入上下文的命名空间列表 ctxt->nsList = xmlAddNs(ctxt->nsList, ds_ns); xmlNodePtr parsed_node = NULL; // 解析XML片段 int err_code = xmlParseBalancedChunkMemory(ctxt, &parsed_node, xml_fragment_str, strlen(xml_fragment_str), NULL); if (err_code != 0) { // 处理解析错误 } // 使用解析后的parsed_node... // 释放资源 xmlFreeParserCtxt(ctxt);
方式二:通过父节点继承命名空间
如果你的XML片段最终要插入到文档的某个父节点下,可以先给父节点绑定目标命名空间,解析时函数会自动继承父节点的命名空间上下文:
// 假设parent是目标父节点,doc是已包含ds命名空间的文档 xmlNsPtr ds_ns = xmlSearchNs(doc, parent, "ds"); if (!ds_ns) { // 异常处理 } // 给父节点绑定命名空间 xmlSetNs(parent, ds_ns); // 直接解析片段,此时会继承父节点的命名空间 xmlNodePtr parsed_node = NULL; int err_code = xmlParseBalancedChunkMemory(NULL, &parsed_node, xml_fragment_str, strlen(xml_fragment_str), parent); if (err_code != 0) { // 错误处理 }
为什么临时方法会生成额外xmlns:ds属性
你之前用的临时方法(比如在片段里手动加xmlns:ds声明),本质是让解析器认为这是新的命名空间声明,所以会在节点上生成额外属性。而上面的正确方式是让解析器复用文档中已有的命名空间定义,不会重复生成声明属性。
内容的提问来源于stack exchange,提问作者codenamezero
相关产品推荐
相关产品推荐

