Как применить последовательно два выражения xpath с помощью libxml? - PullRequest
2 голосов
/ 29 января 2009

Подводя итог, я совершенно новичок в libxml, и мне нужно использовать существующий исходный код. Основная идея заключается в применении первого выражения xpath для извлечения набора узлов из файла XML. Затем для каждого узла применяется второе выражение xpath для извлечения некоторых значений.

Существующий исходный код:

int xt_parseXmlResult(xmlDocPtr doc, const char *xpath, assoc_arrayc_t expr, arrayc_t *result)
{
    xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);

    // Register namespaces ...

    /*
     * Evaluate main xpath expression
     */
    xmlXPathObjectPtr xpathNodes = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx);

    /*
     * Now we apply the xpath expressions on each node returned by the first xpath request
     */
    // First loop is on the XML document as we have to create a new context each
    // time we change the document
    int nbDocs = xpathNodes->nodesetval->nodeNr;

    for (row = 0; row < nbDocs; row++)
    {
        xmlXPathContextPtr  subCtx = xmlXPathNewContext(doc);

        // Register namespaces ...

        // Update context to use the nodeset related to this row
        subCtx->node = xpathNodes->nodesetval->nodeTab[row];

        for (col = 0; col < expr.nbItems; col++)
        {
            // Evaluate expression
            xpathRows = xmlXPathEvalExpression((xmlChar *)expr.itemList[col].val, subCtx);

            result->data[(row + 1) * result->nbCols + col] = strdup((char *)xmlXPathCastToString(xpathRows)); 
            xmlXPathFreeObject(xpathRows);
        }
        xmlXPathFreeContext(subCtx);
        subCtx = NULL;
    }

    xmlFreeDoc(doc); 
    xmlXPathFreeContext(xpathCtx);
    xmlXPathFreeObject(xpathNodes);
    return 0;
}

Я думаю, что проблема в этой строке

    // Update context to use the nodeset related to this row
subCtx->node = xpathNodes->nodesetval->nodeTab[row];

Поскольку второе выражение xpath применяется из корня XML-файла, а не из корня каждого узла.

Есть идеи, как это сделать?

Ответы [ 3 ]

1 голос
/ 07 февраля 2012

как я вижу в узле xmlXPathContext :: предназначен для внутреннего использования библиотеки, поэтому мы не можем использовать его

Возможно, xmlXPtrNewContext должен помочь, но я не могу его использовать.

В настоящее время я делаю трюк с конкатенацией обоих путей и запросом целого. Новый xpath: "(" + xpath1 + ")" + "[num]" + xpath2. Где num можно заменить на любое число между 1 и размером набора результатов xpath1. И это похоже на работу.

1 голос
/ 29 января 2009

вы можете объединить свои выражения xpath.

редактировать

// ПРОГНОЗ / ДЕНЬ / потомок :: content / meteo / desc должен работать

0 голосов
/ 29 января 2009

Пример кода. Изменить в соответствии с вашими потребностями и языком. Это C #, но оно должно быть во многом таким же. Обратите внимание, что второй xpath не начинается с «/» и использует экземпляр узла, возвращенный из первого. Ни один из xpath не заканчивается на "/".

XmlDocument doc = new XmlDocument();
doc.Load(docfile);
XmlNodeList items = doc.SelectNodes("/part1/part2");
foreach (item in items)
{
    XMLNode x = item.SelectNodes("part3");
    //Dostuff
}
...