2

好的,我一直在研究一个类来遍历 html 文档中的所有节点并返回我需要的数据。这非常简单,我已经在 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);
    }
}

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

所以它会降低文档结构,但它如何导航回结构?

xmlNode->children 找到 NULL 时是否返回下一个父节点?据我所知,这不是真的,但我就是不知道这是如何工作的。

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

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

4

2 回答 2

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

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

  3. 这个例子要简单得多,我想了解如何使我的代码更好。
    我假设您编写的课程纯粹是迭代的。递归函数可以极大地简化代码,但在性能方面它们可能会在更大的数据集上引起问题。我肯定会推荐阅读它们;他们可以很有趣。
于 2013-04-04T17:55:28.947 回答
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);
}
于 2013-04-05T21:27:42.000 回答