lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Wednesday 07 March 2007, Wilfred wrote:
>  Hi Greg,
>
>  I would be interested in discussing a common API for Lua.

i've done several tests, trying to find a 'comfortable' way of handling XML in 
Lua.

parsing is (almost) OK with SAX-type APIs, but directly modifying XML is 
challenging.

i realized that a big part of the problem is the syntax.  since XML is a 
horrendous mismatch of features, it's very hard to map it to a simple 
structure.  one naïve attempt would be to map all to a tree, but then text 
content and attributes would be 'special' nodes, and in the end you get a 
monstruosity like DOM.

after a quick glance, E4X looks like DOM without the functions.  that is, XML 
is handled as a tree of objects, with all the quirks of non-tags tree nodes.

so, if it's so hard to come up with a syntax that can express every XML 
(mis)feature, why not use XML itself?

so far, my preferred solution is to turn it backwards: using XML as a template 
that calls Lua for output.  at this time, the lua callbacks have access to 
several other pieces of already-parsed XML, and make it easy to modify 
locally or globally.

the template doesn't have any Lua code, and the Lua code doesn't have any XML 
content.  the only common things are: functions names in the template, and 
you can use attributes, tagnames and tag IDs in Lua.

for example, a template might include this:
----------------- xml --------------
	<tbody function="sched_body">
		<tr>
			<td function="row_var" varname="task" />
			<td function="row_var" varname="priority" />
		</tr>
	</tbody>
---------------- xml end ------------
and the Lua code:
----------------- lua ----------------
require "xlp"

local page = xlp.new_page (in_f, out_f)

function page.cb.sched_body (node)
	page:out_tagstart (node, false)
	for i = 1,10 do
		page:out_content (node, i)
	end
	page:out_tagend (node)
end

function page.cb.row_var (node, row)
	local varname = node.attr.varname
	return xlp.new_node (node, string.format ("%s(%s)", varname, row))
end

page:out()
-------------------- lua end --------------------

the call to xlp.new_page () parses and optimizes the XML.  after that, you can 
populate the callback table (in page.cb) with functions.  the call to 
page:out() processes the XML, calling your Lua functions.

the output looks like:

	<tbody function="sched_body">
		<tr>
			<td function="row_var" varname="feature">feature(1)</td>
			<td function="row_var" varname="task">task(1)</td>
		</tr>
		<tr>
			<td function="row_var" varname="feature">feature(2)</td>
			<td function="row_var" varname="task">task(2)</td>
		</tr>
		<tr>
			<td function="row_var" varname="feature">feature(3)</td>
			<td function="row_var" varname="task">task(3)</td>
		</tr>
	</tbody>

there are a few more features, like being able to reference any XML subtree 
that had an ID, and a very simple function to turn a XML template into a 
Xavante page handler.

if anybody is interested, i might try to document it

-- 
Javier

Attachment: pgpj7zlhj7zmM.pgp
Description: PGP signature