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
家族的反覆運算元會在回傳其父節點之前將其設為 nil。如果迴圈的主體沒有在其他地方保留對下層節點的參照,便會在下一個運算開始時符合垃圾回收條件。請參閱 ConsumingXml。
即使目前尚未實作,其他 consuming 形式可能會與 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
的所有內容。即使對非 lazy 樹狀結構呼叫此函式,也是安全的。
表示不再需要 tree
,而且可以將其刪除。tree
可以是 lazytree 也可以是一般的樹狀結構,而且應該是對其執行的最後一次參照。
雖然目前尚未實作,針對目前正在建立的 lazytree 部分呼叫 consume,可以告訴 lazy parser 不必費心填入樹的該部分。這不是作為一般使用者的工具,而是當消費型過濾反覆器(例如 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
讀取會強制讀取樹的剩餘部分,因為我們不知道樹會持續多長直到結束。