diff -r d2d0bc06eac2 -r 4a61f00ee916 src/lxp/lom.lua --- a/src/lxp/lom.lua Fri Apr 23 21:03:34 2021 +0100 +++ b/src/lxp/lom.lua Fri Apr 23 21:15:05 2021 +0100 @@ -1,12 +1,13 @@ -- See Copyright Notice in license.html --- $Id: lom.lua,v 1.6 2005/06/09 19:18:40 tuler Exp $ local lxp = require "lxp" +local table = require"table" local tinsert, tremove = table.insert, table.remove -local assert, type, print = assert, type, print +local assert, pairs, type = assert, pairs, type +-- auxiliary functions ------------------------------------------------------- local function starttag (p, tag, attr) local stack = p:getcallbacks().stack local newelement = {tag = tag, attr = attr} @@ -32,28 +33,76 @@ end end +-- main function ------------------------------------------------------------- local function parse (o) - local c = { StartElement = starttag, - EndElement = endtag, - CharacterData = text, - _nonstrict = true, - stack = {{}} - } - local p = lxp.new(c) - local status, err - if type(o) == "string" then - status, err = p:parse(o) - if not status then return nil, err end - else - for l in pairs(o) do - status, err = p:parse(l) - if not status then return nil, err end - end - end - status, err = p:parse() - if not status then return nil, err end - p:close() - return c.stack[1][1] + local c = { StartElement = starttag, + EndElement = endtag, + CharacterData = text, + _nonstrict = true, + stack = {{}} + } + local p = lxp.new(c) + local to = type(o) + if to == "string" then + local status, err, line, col, pos = p:parse(o) + if not status then return nil, err, line, col, pos end + else + local iter, state, init + if to == "table" then + iter, state, init = pairs(o) + elseif to == "function" then + iter = o + elseif to == "userdata" and o.read then + iter, state = o.read, o + else + error ("Bad argument #1 to parse: expected a string, a table, a function or a file, but got "..to, 2) + end + for l in iter, state, init do + local status, err, line, col, pos = p:parse(l) + if not status then return nil, err, line, col, pos end + end + end + local status, err, line, col, pos = p:parse() -- close document + if not status then return nil, err, line, col, pos end + p:close() + return c.stack[1][1] end -return { parse = parse } +-- utility functions --------------------------------------------------------- +local function find_elem (self, tag) + if self.tag == tag then + return self + end + for i = 1, #self do + local v = self[i] + if type(v) == "table" then + local found = find_elem (v, tag) + if found then + return found + end + end + end + return nil +end + +local function list_children (self, tag) + local i = 0 + return function () + i = i+1 + local v = self[i] + while v do + if type (v) == "table" and (tag == nil or tag == v.tag) then + return v + end + i = i+1 + v = self[i] + end + return nil + end +end + +return { + find_elem = find_elem, + list_children = list_children, + parse = parse, +}