【问题标题】:libxml2 Copy node without namespace or replace/remove namespacelibxml2 复制没有命名空间的节点或替换/删除命名空间
【发布时间】:2018-03-19 06:29:32
【问题描述】:

我有一些类似的xml

<node xmlns="path/to/namespace">
  <grammar prop1="bla-bla-bla" prop2="etc">
    <!-- ... -->
  </grammar>
</node>

我想获取语法标签,设置我的命名空间并保存所有属性(prop1,prop2),子节点等等。 我只是转到语法标签并致电xmlNodePtr copied = xmlCopyNode(node, 1);。 之后我删除了一些属性,添加新的等等(复制)。 之后我想将命名空间"/path/to/namespace" 替换为"/path/to/namespace2"。 没有像xmlRemoveNsxmlReplaceNs这样的函数,所以我只是释放命名空间并设置新的。

if (copied->ns)
{
  xmlFree((void*)copied->ns->href);
  copied->ns->href = xmlStrdup((const xmlChar *)"/path/to/namespace2");
}

但它看起来很奇怪而且有点糟糕。 有没有办法替换命名空间,复制没有命名空间或删除命名空间并设置新的?

【问题讨论】:

    标签: xml libxml2


    【解决方案1】:

    函数xmlFree() 仅释放由某些库函数分配的内存,这不是您要搜索的。

    尝试使用例如xmlSetNsProp():

    xmlAttrPtr xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar * name, const xmlChar * value)
    

    设置(或重置)节点携带的属性。 ns 结构必须在作用域内,这个不检查

    节点:节点

    ns:命名空间定义

    name:属性名称

    value:属性值

    返回:属性指针。

    您将在此处找到更多信息:http://xmlsoft.org/html/libxml-tree.html 而且我认为您可以找到最适合您需求的功能。

    在源代码中,命名空间似乎是ns-&gt;href

    /**
     * xmlSetNsProp:
     * @node:  the node
     * @ns:  the namespace definition
     * @name:  the attribute name
     * @value:  the attribute value
     *
     * Set (or reset) an attribute carried by a node.
     * The ns structure must be in scope, this is not checked
     *
     * Returns the attribute pointer.
     */
    xmlAttrPtr xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, const xmlChar *value)
        {
        xmlAttrPtr prop;
    
        if(ns && (ns->href == NULL))
            return (NULL);
        prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
        if(prop != NULL)
            {
            /*
             * Modify the attribute's value.
             */
            if(prop->atype == XML_ATTRIBUTE_ID)
                {
                xmlRemoveID(node->doc, prop);
                prop->atype = XML_ATTRIBUTE_ID;
                }
            if(prop->children != NULL)
                xmlFreeNodeList(prop->children);
            prop->children = NULL;
            prop->last = NULL;
            prop->ns = ns;
            if(value != NULL)
                {
                xmlNodePtr tmp;
    
                if(!xmlCheckUTF8(value))
                    {
                    xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr)node->doc,
                    NULL);
                if (node->doc != NULL)
                node->doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
                }
            prop->children = xmlNewDocText(node->doc, value);
            prop->last = NULL;
            tmp = prop->children;
            while(tmp != NULL)
                {
                tmp->parent = (xmlNodePtr)prop;
                if(tmp->next == NULL)
                    prop->last = tmp;
                tmp = tmp->next;
                }
            }
        if(prop->atype == XML_ATTRIBUTE_ID)
            xmlAddID(NULL, node->doc, value, prop);
        return (prop);
        }
    /*
     * No equal attr found; create a new one.
     */
    return (xmlNewPropInternal(node, ns, name, value, 0));
    }
    

    【讨论】:

    • 我不认为这是我需要的,因为我想更改 href,而不是属性。 Href 不被视为属性。我之前也访问过 xmlsoft.org,但我的问题没有解决方案。
    • 在源代码中,命名空间似乎是 ns->href,请检查编辑后的答案
    • 我检查了这个功能,但这不是我想要的,我想改变ns-&gt;href,但是没有那个功能。据我了解 - 这样做的唯一方法是创建新命名空间,并调用 xmlSetNs,但我无法创建默认命名空间,因为它已经存在于此节点中。
    • 好的,我意识到我可以在没有节点的情况下创建新的命名空间。但是现在在xmlNodeDump 之后,我得到了没有 xmlns 的语法标签,这很奇怪。
    【解决方案2】:

    这似乎有效

    xmlSetNs(copied, nullptr);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-14
      相关资源
      最近更新 更多