libxml++ 文本阅读器;跳过节点
libxml++ TextReader; Skipping nodes
我正在使用 libxml++ 解析相当大的 XML 文件,因此无法使用 DOM。
假设我有一个 XML 文件,例如:
<?xml version="1.0"?>
<root>
<book name="book1">
<chapter name="chapter1">
#Pages
</chapter>
<chapter name="chapter2">
#Pages
</chapter>
</book>
<book name="book2">
<chapter name="chapter1">
#Pages
</chapter>
<chapter name="chapter2">
#Pages
</chapter>
</book>
<book name="book3">
<chapter name="chapter1">
</chapter>
#Pages
<chapter name="chapter2">
#Pages
</chapter>
</book>
</root>
有没有一种方法可以循环遍历所有书籍,而不必使用 TextReader 处理嵌套节点?
通常 SAX 解析器可以吗?
编辑:
移动解决方案来回答。
我可能找到了(部分)解决方案。
而 read() 读取下一个节点并因此移动到 'deeper' 层,而 next() 跳转到当前深度的下一个节点。调用 read() 两次将 reader 移动到第一本书的开始标签(深度 1)。现在调用 next() 会导致 reader 跳转到深度为 1 的下一个节点,在本例中为结束标记。现在可以通过调用 next() 遍历所有书籍,因为如果没有更多深度为 1 的节点,它将 return false
不幸的是,没有选项可以将 reader 向上移动到树中,因此如果您在循环内调用 read() 并移动到更深的层,next() 将跳转到这一层的下一个节点,所以在大多数情况下这可能不是一个令人满意的答案。
另一种方法是在 reader 上调用 get_current_node(),然后使用 get_children() 检索直接子节点的列表。
在此示例中,可以调用 read() 将 reader 移动到根节点,然后分别调用 get_current_node() 和 get_children 并遍历 'book' 的结果列表节点。
这似乎只适用于小文件,因为调用 get_children() 具有许多子节点的节点可能会导致缩短列表,只有所有子节点的一小部分显示。
我发现的一个可能的解决方法是导航到所需的深度(如上所述),通过调用 next() 在该深度的节点上循环,并在每次循环之后,通过调用 expand( ) 在 TextReader 上,它展开当前节点及其所有子树。
这样您就可以通过访问新节点来处理子树,而无需更改 TextReader 对象。
但是,要小心。新节点的C++-Wrapper不会被删除,除非你调用free_wrapper().
来自文档:
The C++ wrappers are not deleted. Using this method (expand()) causes memory
leaks, unless you call xmlpp::Node::free_wrappers(), which is not
intended to be called by the application.
请注意,这是我自己的观察,因为函数文档非常稀疏或不完整。
我正在使用 libxml++ 解析相当大的 XML 文件,因此无法使用 DOM。
假设我有一个 XML 文件,例如:
<?xml version="1.0"?>
<root>
<book name="book1">
<chapter name="chapter1">
#Pages
</chapter>
<chapter name="chapter2">
#Pages
</chapter>
</book>
<book name="book2">
<chapter name="chapter1">
#Pages
</chapter>
<chapter name="chapter2">
#Pages
</chapter>
</book>
<book name="book3">
<chapter name="chapter1">
</chapter>
#Pages
<chapter name="chapter2">
#Pages
</chapter>
</book>
</root>
有没有一种方法可以循环遍历所有书籍,而不必使用 TextReader 处理嵌套节点? 通常 SAX 解析器可以吗?
编辑: 移动解决方案来回答。
我可能找到了(部分)解决方案。
而 read() 读取下一个节点并因此移动到 'deeper' 层,而 next() 跳转到当前深度的下一个节点。调用 read() 两次将 reader 移动到第一本书的开始标签(深度 1)。现在调用 next() 会导致 reader 跳转到深度为 1 的下一个节点,在本例中为结束标记。现在可以通过调用 next() 遍历所有书籍,因为如果没有更多深度为 1 的节点,它将 return false
不幸的是,没有选项可以将 reader 向上移动到树中,因此如果您在循环内调用 read() 并移动到更深的层,next() 将跳转到这一层的下一个节点,所以在大多数情况下这可能不是一个令人满意的答案。
另一种方法是在 reader 上调用 get_current_node(),然后使用 get_children() 检索直接子节点的列表。 在此示例中,可以调用 read() 将 reader 移动到根节点,然后分别调用 get_current_node() 和 get_children 并遍历 'book' 的结果列表节点。
这似乎只适用于小文件,因为调用 get_children() 具有许多子节点的节点可能会导致缩短列表,只有所有子节点的一小部分显示。
我发现的一个可能的解决方法是导航到所需的深度(如上所述),通过调用 next() 在该深度的节点上循环,并在每次循环之后,通过调用 expand( ) 在 TextReader 上,它展开当前节点及其所有子树。 这样您就可以通过访问新节点来处理子树,而无需更改 TextReader 对象。
但是,要小心。新节点的C++-Wrapper不会被删除,除非你调用free_wrapper().
来自文档:
The C++ wrappers are not deleted. Using this method (expand()) causes memory leaks, unless you call xmlpp::Node::free_wrappers(), which is not intended to be called by the application.
请注意,这是我自己的观察,因为函数文档非常稀疏或不完整。