Lazy Tree |
|
(这是 LazyKit 的一部分。)
LazyTree 在其内容被引用时,会构造一个看起来像传统的 XmlTree,根据需要在解析更多源文档以按需填充内容。
为什么这很有趣?树是处理 XML 文档的自然数据模型。一个简单的树实现一次性将整个文档读入内存。对于大型文档,这可能代价过高。尽管回调和事件 API 内存效率很高,但编程起来很痛苦。
给定风格化的迭代器,内存消耗可以限制在特定的子树。考虑
for i,child in xnpairs_c(tree) do
if child.attr.href then
print(child.name)
table.insert(references, child)
end
end
其中 _c 系列迭代器在返回节点之前将其从父节点中置空。如果循环体不在其他地方保留对子节点的引用,一旦下一个迭代开始,它将符合垃圾回收的条件。参见 ConsumingXml。
尽管尚未实现,但其他消耗形式可以与 XML 解析器交互以节省更多资源
<document> <firstname>Jay</firstname> <lastname>Carlson</lastname> <bodytext>Spending too much time listening to <ref>In Utero</ref> can be [...] <title>I Think I'm DOM</title>
lastname, title = xmlextract.strings_consume(tree, "lastname", "title")
strings_consume 过滤器可以潜在地关闭任何它知道不需要的节点(如 bodytext)内的字符数据和其他事件,因为对它们的引用不可能影响程序的其余部分。
lazytree 依赖于 lxpevent 来生成事件队列,而 lxpevent 依赖于 LuaExpat?。
对尚未完全加载的 lazytree 调用正常的 ipairs 迭代器将不起作用,因为 ipairs(lz) 不直接引用 lz.n。请使用 XmlIter 迭代器 xpairs{_c} 和 xnpairs{_c};后者更方便。参见 XmlIter。
返回一个从字符串 s 中懒惰解析的树。
从 file 中返回一个懒惰解析的树。如果 file 是一个字符串,它将被解释为文件名并打开;否则,file 被视为一个 io 库文件对象。
从 lxpevent event_source 中返回一个懒惰解析的树。
强制读取 tree 的全部内容。对非懒惰树调用此函数是安全的。
指示 tree 不再需要,可以销毁。tree 可以是 lazytree 或常规树,并且应该是对其的最后一个引用。
尽管尚未实现,但对 lazytree 当前正在构建的部分调用 consume 可以告诉懒惰解析器不要去填充该部分树。这并非旨在作为通用的用户工具;相反,它是一个原始工具,可以被消耗性过滤迭代器(如 xmliter.switch)使用,当它们注意到遇到的树将被跳过且在应用程序中没有可见性时。
在不进一步解析的情况下打印 lazytree 的当前内容。用于演示目的。
<paragraph justify='centered'>first child<b>bold</b>second child</paragraph>
lz = {name="paragraph", attr={justify="centered"},
"first child",
{name="b", "bold", n=1},
"second child",
n=3
}
lz = {name="paragraph", attr={justify="centered"},
_read_so_far=0
}
lz[1] 之后,它将包含
lz = {name="paragraph", attr={justify="centered"},
"first child",
_read_so_far=1
}
lz[2] 之后
lz = {name="paragraph", attr={justify="centered"},
"first child",
{name="b", _read_so_far=0}
}
lz[3] 的引用将强制完成 lz[2] 的全部内容
lz = {name="paragraph", attr={justify="centered"},
"first child",
{name="b", "bold", n=1}
"second child",
_read_so_far=3
}
lz[4](它是 nil)或 lz.n 将强制完成树的解析。
请注意,从 lz.n 读取将强制读取树的剩余部分,因为我们不知道它会何时关闭。