Синтаксический анализ результатов XML в дубликатах с использованием libxml2 - PullRequest
0 голосов
/ 10 ноября 2010

Я использую libxml2 для анализа следующей строки XML:

<?xml version=\"1.0\"?>
<note>
    <to>
        <name>Tove</name>
        <name>Tovi</name>
    </to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>

Отформатирован как строка в стиле C:

"<?xml version=\"1.0\"?><note><to><name>Tove</name><name>Tovi</name></to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"

Это основано на примере из W3Cсайт на XML;Я добавил только вложенные имена в поле «to».

У меня есть следующий рекурсивный код в C ++ для анализа его в дереве объектов:

RBCXMLNode * RBCXMLDoc::recursiveProcess(xmlNodePtr node) {
    RBCXMLNode *rNode = new RBCXMLNode();
    xmlNodePtr childIterator = node->xmlChildrenNode;

    const char *chars = (const char *)(node->name);
    string name(chars);
    const char *content = (const char *)xmlNodeGetContent(node);
    rNode->setName(name);
    rNode->setUTF8Data(content);
    cout << "Just parsed " << rNode->name() << ": " << rNode->stringData() << endl;
    while (childIterator != NULL) {
        RBCXMLNode *rNode2 = recursiveProcess(childIterator);
        rNode->addChild(rNode2);
        childIterator = childIterator->next;
    }
    return rNode;
}

Так что для каждого узла он создаетсоответствующий объект устанавливает его имя и содержимое, а затем рекурсивно для его дочерних элементов.Обратите внимание, что каждый узел обрабатывается только один раз.Тем не менее, я получаю следующий (бессмысленный, по крайней мере для меня) вывод:

Только что проанализировал примечание: ToveToviJaniReminder Не забывайте меня на этих выходных!
Просто проанализировал: ToveTovi
Только что проанализировал имя: Tove
Просто проанализировал текст: Tove
Просто проанализировал имя: Tovi
Просто проанализировал текст: Tovi
Просто проанализировал с: Jani
Просто проанализировал текст: Jani
Простопроанализированный заголовок: напоминание
только что проанализированный текст: напоминание
только что проанализированное тело: не забывайте меня в эти выходные!
просто проанализированный текст: не забывайте меня в эти выходные!

Обратите внимание, что каждый элемент анализируется дважды;один раз давая имя как «текст», а другой - как оно должно быть.Кроме того, корневой узел «примечания» также анализирует свои данные;это нежелательно.Также обратите внимание, что этот корневой узел не анализируется дважды, как остальные.

Итак, у меня есть два вопроса:

  1. Как мне избежать анализа данных корневого узла, и простоего имя, а не его содержание?Это также, вероятно, произойдет и с более глубоко вложенными узлами.
  2. Как избежать повторного разбора на других узлах?Очевидно, я хочу сохранить версии с правильными именами, сохраняя (маловероятную) вероятность того, что узел на самом деле называется «текст».Кроме того, могут быть желательные дублирующие узлы, поэтому просто проверить, был ли уже проанализирован узел, не вариант.

Заранее спасибо.

1 Ответ

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

Основная проблема, которую я вижу в вашем коде, заключается в том, что вы звоните xmlNodeGetContent().Это возвращает вам весь текст внутри тега и его конечного аналога.

При синтаксическом анализе с libxml2 вы получаете несколько узлов, содержимое которых является сложным, поэтому вы не можете полагаться на xmlNodeGetContent() для извлечениясодержимое.Вы должны сделать рекурсивную функцию по-другому.Например, самым быстрым решением для вашей функции было бы напечатать имя узла только для узлов, которые не являются текстовыми (проверено с помощью xmlNodeIsText()), и написать просто xmlNodeGetContent() для узлов, которые являются текстовыми.Это даст вам что-то вроде:

Just parsed note
Just parsed to
Just parsed name
Just parsed text: Tove
Just parsed name
Just parsed text: Tovi
...

Обратите внимание, что теперь вы печатаете только элементы, и только текст, когда у вас есть тип текстового элемента.

Этотакже имеет смысл концептуально, потому что содержимое нетекстового узла (не текста) настолько сложно, как вы его печатаете?Вы можете только напечатать его этикетку (имя).Однако текстовые узлы настолько просты, что вы можете напечатать их содержимое.

...