libXML:检查节点是否已经取消链接并释放

libXML: check if node is already unlinked and freed

我正在使用 libxml2 解析 html 文档并根据 xpath 查询删除一些元素。例如,我想删除所有包含 "display: none" 的元素:

stripNode(doc, "//*[contains(@style,'display:none')]");

...

public static void stripNode(Html.Doc* doc, string xpath)
{
    Xml.XPath.Context cntx = new Xml.XPath.Context(doc);
    Xml.XPath.Object* res = cntx.eval_expression(xpath);

    if(res != null
    && res->type == Xml.XPath.ObjectType.NODESET
    && res->nodesetval != null)
    {
        for(int i = 0; i < res->nodesetval->length(); ++i)
        {
            Xml.Node* node = res->nodesetval->item(i);
            if(node != null)
            {
                node->unlink();
                node->free_list();
            }
        }
    }

    delete res;
}

但我遇到的文档中有一个 "display: none" 的元素包含在另一个 "display: none" 的元素中。现在,当顺序更高的元素被取消链接并释放时,它的所有子元素也都消失了。但是第二个元素仍然是 "res" 的一部分,而不是 "null"。所以我因为双重免费而崩溃。

有没有办法检查节点是否仍然是文档的一部分或已经被释放。或者,有没有办法只查找 xpath 查询的第一个匹配项,并在节点取消链接和释放后查找下一个匹配项? 我猜执行

cntx.eval_expression(xpath);

在每个未链接的节点之后再次运行会非常慢。

感谢您的帮助:)

我建议另一种方法来实现相同的目的。您可以使用更具体的 xpath,这样如果有 nested 元素具有 style 属性包含 "display:none",只有 outer-most 个元素被选中:

//*[contains(@style,'display:none')][not(ancestor::*[contains(@style,'display:none')])]