src/lxp/lom.lua

changeset 36
4a61f00ee916
parent 10
e981a82571cf
--- 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,
+}

mercurial