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')])]
我正在使用 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')])]