последовательные xmlXPathEval's с libxml2 - PullRequest
0 голосов
/ 24 ноября 2010

Я использую libxml2 для разбора HTML-документа, и у меня возник вопрос.В чем разница между

xmlXPathObjectPtr obj = xmlXPathEval((xmlChar*)"//div[@id='gall_list']//td//h3/img[@alt]", ctx);
printf("%d", obj->nodesetval->nodeNr);

и

xmlXPathObjectPtr obj1 = xmlXPathEval((xmlChar*)"//div[@id='gall_list']//td//h3", ctx);
xmlXPathObjectPtr obj2 = xmlXPathEval((xmlChar*)"img[@alt]", ctx);
printf("%d", obj2->nodesetval->nodeNr);

?Если я прав, они должны быть одинаковыми, верно?Но второй не работает правильно.Я изменил часть «img [@alt]» части obj2 на «./img[@alt]», но она тоже не сработала.второй?Просто к вашему сведению, следующий работал правильно:

xmlXPathObjectPtr obj1 = xmlXPathEval((xmlChar*)"//div[@id='gall_list']//td", ctx);
xmlXPathObjectPtr obj2 = xmlXPathEval((xmlChar*)".//h3/img[@alt]", ctx);
printf("%d", obj2->nodesetval->nodeNr);

Заранее большое спасибо!

Ответы [ 2 ]

2 голосов
/ 24 ноября 2010

Я смотрю на документы для xmlXPathEval () и не вижу причины, по которой первые два блока кода должны делать то же самое: Другими словами, почему процессор XPath должен на контекст при оценке второго XPath повлияет оценка первого? В документе не сказано, что xmlXPathEval () изменит передаваемый контекст ... Это делает xmlXPathEval ()?

Мне кажется, что вам нужно сделать, чтобы ваш второй пример кода заработал, это передать ctx, основанный на obj1 (результат первого xmlXPathEval ()), в качестве второго аргумента второй xmlXPathEval (). Однако я не вижу, как извлечь xmlXPathContextPtr из xmlXPathObjectPtr.

Причина, по которой ваш третий пример кода "работает", заключается в том, что результат первой оценки XPath игнорируется; выражение XPath .//h3/img[@alt] выберет указанные элементы <img>, когда контекст является просто корневым узлом (/). Но он будет соответствовать всем элементам img, которые являются потомками элементов h3 и имеют атрибут alt, не только тех, которые являются потомками div[@id='gall_list'].

1 голос
/ 24 ноября 2010

Ваши первые два фрагмента кода должны определенно вести себя по-разному, поскольку xmlXPathEval работает на одном и том же узле контекста для обоих выражений.В третьем фрагменте вы ищете все потомки (//) узла контекста. Если этот узел является элементом документа, то будут возвращены все элементы img с атрибутами alt внутри элемента h3.Контекст не изменяется автоматически в зависимости от результата первого вызова.

Можно установить узел контекста самостоятельно через поле node поля xmlXPathContext, как в следующем фрагменте.Обратите внимание, что я перевел это из vala и не проверял имена типов.

xmlXPathObjectPtr obj1 = xmlXPathEval((xmlChar*)"//div[@id='gall_list']//td//h3", ctx);
xmlXPathNodeSetPtr nodeset = obj1->nodesetval;
xmlNodePtr node = nodeset->item(0);

// Set the context node for the following xpath expressions
ctx.node = node;
xmlXPathObjectPtr obj2 = xmlXPathEval((xmlChar*)"img[@alt]", ctx);
...