C ++ libxml xmlNode-> children

时间:2013-04-04 17:09:24

标签: c++ xml-parsing libxml2

好的,我一直在研究一个类来遍历html doc中的所有节点并返回我需要的数据。这很简单,我已经在Bash中实现了这一点,但现在我正在尝试将其移植到C ++中。

我从libxml网站上的示例开始,但是我逐个节点地逐步完成了这个功能,我无法理解它是如何工作的。

这是功能:

    static void
print_element_names(xmlNode * a_node)
{
    xmlNode *cur_node = NULL;

    for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
        if (cur_node->type == XML_ELEMENT_NODE) {
            printf("node type: Element, name: %s\n", cur_node->name);
        }

        print_element_names(cur_node->children);
    }
}

基本上,这个函数将节点分配给指针,并开始循环遍历所有兄弟节点,但如果当前节点有子节点,它会调用该函数并从该子节点重新开始。这一切都是可以理解的。

因此它推动了doc结构,但它如何导航结构?

xmlNode->子节点在找到NULL时会返回下一个父节点吗?据我所知,这不是真的,但我无法弄清楚这是如何运作的。

我成功地创建了一个类来做我想要的,但它比这复杂得多,大约10行。我实际上必须检查下一个节点是否为空,如果它有子节点则向下导航或向后导航,如果没有则向下导航到下一个节点。

这个例子更简单,我想了解如何使我的代码更好。

2 个答案:

答案 0 :(得分:2)

  1. 因此它推动了文档结构,但它如何导航结构? 你发布的是一个递归函数。从你问题的性质来看,我假设你不太了解递归是什么/它是如何工作的。快速谷歌搜索应该给你一些很好的信息/例子。

  2. xmlNode->子节点在找到NULL时返回下一个父节点吗? 我假设xmlNode-> children返回指向包含当前节点的所有子节点的链表的指针。如果当前节点没有子节点,则可能返回NULL。

  3. 这个例子更简单,我想了解如何使我的代码更好 我假设你写的课程纯粹是迭代的。递归函数可以大大简化代码,但性能方面它们可能会导致更大的数据集出现问题。我肯定会建议阅读它们;他们可以很有趣。

答案 1 :(得分:0)

迭代地解决问题本质上是树遍历。您将需要一个堆栈来完成此任务。堆栈可能最容易实现为单链表。

// interface to be implemented
typedef void* Stack;
Stack stack_new();  // creates a new stack
void stack_add(Stack stack, xmlNode *element); // adds an element to the stack
int stack_size(); // returns the number of elements currently in the stack
xmlNode* stack_remove(Stack stack); // pops an element from the stack
void stack_free(Stack stack); // frees up resources used by the stack

// printing code
static void print_element_names(xmlNode *a_node)
{
    Stack stack = stack_new();
    stack_add(stack, a_node);

    while(stack_size(stack))
    {
            xmlNode *cur_node = stack_remove(stack);
            if(cur_node->children) stack_add(cur_node->children);
            xmlNode *iter_node = NULL;
            for (iter_node = cur_node; iter_node; iter_node = iter_node->next)
            {
                if (iter_node->type == XML_ELEMENT_NODE) 
                    printf("node type: Element, name: %s\n", iter_node->name);
            }
    }

    stack_free(stack);
}