mirror of
https://github.com/civetweb/civetweb
synced 2025-03-28 21:13:27 +00:00
Update LuaXML
The original version of LuaXML used in CivetWeb was written by: Copyright (C) 2007-2013 Gerald Franz, eludi.net It used to be hosted on http://viremo.eludi.net/LuaXML/index.html, however, this site is down already since a couple of years. An extended version of LuaXML was created by Bernhard Nortmann. It is hosted on GitHub: https://github.com/n1tehawk/LuaXML
This commit is contained in:
parent
fdaa5260e1
commit
6d87359d6c
@ -146,6 +146,11 @@ LuaXML License
|
||||
|
||||
### Included only if built with Lua and LuaXML support.
|
||||
|
||||
Version 1.8.0 (Lua 5.2), 2013-06-10 by Gerald Franz, eludi.net
|
||||
|
||||
Modified and extended 2015 by Bernhard Nortmann, https://github.com/n1tehawk/LuaXML – version 2.0.x, compatible with Lua 5.1 to 5.3 and LuaJIT.
|
||||
|
||||
|
||||
> LuaXML License
|
||||
>
|
||||
> LuaXml is licensed under the terms of the MIT license reproduced below,
|
||||
|
@ -132,7 +132,7 @@ simplicity by a carefully selected list of features:
|
||||
|
||||
[](http://lua.sqlite.org/index.cgi/index)
|
||||
|
||||
[](http://viremo.eludi.net/LuaXML/index.html)
|
||||
[](https://github.com/n1tehawk/LuaXML)
|
||||
|
||||
[](http://duktape.org)
|
||||
|
||||
|
@ -102,7 +102,7 @@
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>MG_EXPERIMENTAL_INTERFACES;USE_SERVER_STATS;USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>MG_EXPERIMENTAL_INTERFACES;USE_SERVER_STATS;USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_LUA_LUAXML;USE_WEBSOCKET;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\src\third_party\duktape-1.5.2\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -146,7 +146,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>MG_EXPERIMENTAL_INTERFACES;USE_SERVER_STATS;USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>MG_EXPERIMENTAL_INTERFACES;USE_SERVER_STATS;USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_LUA_LUAXML;USE_WEBSOCKET;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\src\third_party\duktape-1.5.2\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
@ -2173,6 +2173,8 @@ civetweb_open_lua_libs(lua_State *L)
|
||||
{
|
||||
extern int luaopen_LuaXML_lib(lua_State *);
|
||||
luaopen_LuaXML_lib(L);
|
||||
// lua_pushvalue(L, -1); to copy value
|
||||
lua_setglobal(L, "xml");
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_LUA_FILE_SYSTEM)
|
||||
|
244
src/third_party/LuaXML.lua
vendored
244
src/third_party/LuaXML.lua
vendored
@ -1,116 +1,154 @@
|
||||
local base = _G
|
||||
--[[--
|
||||
|
||||
-- symbolic name for tag index, this allows accessing the tag by var[xml.TAG]
|
||||
xml.TAG = 0
|
||||
A module that maps between Lua and XML without much ado.
|
||||
|
||||
-- sets or returns tag of a LuaXML object
|
||||
function xml.tag(var,tag)
|
||||
if base.type(var)~="table" then return end
|
||||
if base.type(tag)=="nil" then
|
||||
return var[xml.TAG]
|
||||
end
|
||||
var[xml.TAG] = tag
|
||||
end
|
||||
LuaXML provides a set of functions for processing XML data in Lua.
|
||||
It offers a very simple and natural mapping between the XML format and Lua tables,
|
||||
which allows one to work with and construct XML data just using Lua's normal
|
||||
table access and iteration methods (e.g. `ipairs()`).
|
||||
|
||||
-- creates a new LuaXML object either by setting the metatable of an existing Lua table or by setting its tag
|
||||
function xml.new(arg)
|
||||
if base.type(arg)=="table" then
|
||||
base.setmetatable(arg,{__index=xml, __tostring=xml.str})
|
||||
return arg
|
||||
end
|
||||
local var={}
|
||||
base.setmetatable(var,{__index=xml, __tostring=xml.str})
|
||||
if base.type(arg)=="string" then var[xml.TAG]=arg end
|
||||
return var
|
||||
end
|
||||
Substatements and tag content are represented as array data having numerical
|
||||
keys (`1 .. n`), attributes use string keys, and tags the numerical index `0`.
|
||||
This representation makes sure that the structure of XML data is preserved
|
||||
exactly across read/write cycles (i.e. `xml.eval(var:str())` should equal `var`
|
||||
again).
|
||||
|
||||
-- appends a new subordinate LuaXML object to an existing one, optionally sets tag
|
||||
function xml.append(var,tag)
|
||||
if base.type(var)~="table" then return end
|
||||
local newVar = xml.new(tag)
|
||||
var[#var+1] = newVar
|
||||
return newVar
|
||||
end
|
||||
---
|
||||
|
||||
-- converts any Lua var into an XML string
|
||||
function xml.str(var,indent,tagValue)
|
||||
if base.type(var)=="nil" then return end
|
||||
local indent = indent or 0
|
||||
local indentStr=""
|
||||
for i = 1,indent do indentStr=indentStr.." " end
|
||||
local tableStr=""
|
||||
<br>To use LuaXML, first import the module - for example like this:
|
||||
local xml = require("LuaXML")
|
||||
|
||||
if base.type(var)=="table" then
|
||||
local tag = var[0] or tagValue or base.type(var)
|
||||
local s = indentStr.."<"..tag
|
||||
for k,v in base.pairs(var) do -- attributes
|
||||
if base.type(k)=="string" then
|
||||
if base.type(v)=="table" and k~="_M" then -- otherwise recursiveness imminent
|
||||
tableStr = tableStr..xml.str(v,indent+1,k)
|
||||
else
|
||||
s = s.." "..k.."=\""..xml.encode(base.tostring(v)).."\""
|
||||
end
|
||||
end
|
||||
LuaXML consists of a Lua file (`LuaXML.lua`) and a corresponding C module
|
||||
(`LuaXML_lib`) - normally a shared library (`.dll`/`.so`), although a static
|
||||
linking is possible as well. Both parts are imported by this call, provided
|
||||
that they are found in Lua's package search path.
|
||||
|
||||
|
||||
@module LuaXML
|
||||
]]
|
||||
local _M = require("LuaXML_lib")
|
||||
|
||||
--[[-- saves a Lua var as XML file.
|
||||
Basically this simply exports the string representation `xml.str(var)`
|
||||
(or `var:str()`), plus a standard header.
|
||||
|
||||
@function save
|
||||
@param var the variable to be saved, normally a table
|
||||
@tparam string filename the filename to be used. An existing file of the same name gets overwritten.
|
||||
@tparam ?string filemode the file mode to pass to `io.open`, defaults to "w"
|
||||
|
||||
@tparam ?string cmt
|
||||
custom _comment_ to be written at the top of the file (after the header). You
|
||||
may pass an empty string if you don't want any comment at all, otherwise it
|
||||
should preferably end with at least one newline. Defaults to:
|
||||
<!-- file «filename», generated by LuaXML -->\n\n
|
||||
|
||||
@tparam ?string hdr
|
||||
custom _header_, written before anything else. You may pass an empty string if
|
||||
you don't want any header at all, otherwise it should preferably end with a
|
||||
newline. Defaults to the standard XML 1.0 declaration:
|
||||
<?xml version="1.0"?>\n
|
||||
|
||||
@usage
|
||||
var:save("simple.xml")
|
||||
var:save("no-comment.xml", nil, "")
|
||||
var:save("custom.xml", "a+", "<!-- append mode, no header -->\n", "")
|
||||
]]
|
||||
function _M.save(var, filename, filemode, comment, header)
|
||||
if var and filename and #filename > 0 then
|
||||
local file, err = io.open(filename, filemode or "w")
|
||||
if not file then
|
||||
error('error opening "' .. filename .. '" for saving: ' .. err)
|
||||
end
|
||||
if #var==0 and #tableStr==0 then
|
||||
s = s.." />\n"
|
||||
elseif #var==1 and base.type(var[1])~="table" and #tableStr==0 then -- single element
|
||||
s = s..">"..xml.encode(base.tostring(var[1])).."</"..tag..">\n"
|
||||
else
|
||||
s = s..">\n"
|
||||
for k,v in base.ipairs(var) do -- elements
|
||||
if base.type(v)=="string" then
|
||||
s = s..indentStr.." "..xml.encode(v).." \n"
|
||||
else
|
||||
s = s..xml.str(v,indent+1)
|
||||
end
|
||||
end
|
||||
s=s..tableStr..indentStr.."</"..tag..">\n"
|
||||
end
|
||||
return s
|
||||
else
|
||||
local tag = base.type(var)
|
||||
return indentStr.."<"..tag.."> "..xml.encode(base.tostring(var)).." </"..tag..">\n"
|
||||
file:write(header or '<?xml version="1.0"?>\n')
|
||||
file:write(comment or
|
||||
'<!-- file "' .. filename .. '", generated by LuaXML -->\n\n')
|
||||
file:write(_M.str(var))
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
|
||||
--[[-- iterate subelements ("XML children") as _key - value_ pairs.
|
||||
This function is meant to be called in a generic `for` loop, similar to what
|
||||
`ipairs(var)` would do. However you can easily specify additional criteria
|
||||
to `match` against here, possibly reducing the overhead needed to test for
|
||||
specific subelements.
|
||||
|
||||
-- saves a Lua var as xml file
|
||||
function xml.save(var,filename)
|
||||
if not var then return end
|
||||
if not filename or #filename==0 then return end
|
||||
local file = base.io.open(filename,"w")
|
||||
file:write("<?xml version=\"1.0\"?>\n<!-- file \"",filename, "\", generated by LuaXML -->\n\n")
|
||||
file:write(xml.str(var))
|
||||
base.io.close(file)
|
||||
end
|
||||
|
||||
|
||||
-- recursively parses a Lua table for a substatement fitting to the provided tag and attribute
|
||||
function xml.find(var, tag, attributeKey,attributeValue)
|
||||
-- check input:
|
||||
if base.type(var)~="table" then return end
|
||||
if base.type(tag)=="string" and #tag==0 then tag=nil end
|
||||
if base.type(attributeKey)~="string" or #attributeKey==0 then attributeKey=nil end
|
||||
if base.type(attributeValue)=="string" and #attributeValue==0 then attributeValue=nil end
|
||||
-- compare this table:
|
||||
if tag~=nil then
|
||||
if var[0]==tag and ( attributeValue == nil or var[attributeKey]==attributeValue ) then
|
||||
base.setmetatable(var,{__index=xml, __tostring=xml.str})
|
||||
return var
|
||||
end
|
||||
else
|
||||
if attributeValue == nil or var[attributeKey]==attributeValue then
|
||||
base.setmetatable(var,{__index=xml, __tostring=xml.str})
|
||||
return var
|
||||
end
|
||||
end
|
||||
-- recursively parse subtags:
|
||||
for k,v in base.ipairs(var) do
|
||||
if base.type(v)=="table" then
|
||||
local ret = xml.find(v, tag, attributeKey,attributeValue)
|
||||
if ret ~= nil then return ret end
|
||||
end
|
||||
end
|
||||
For the resulting `(k, v)` pairs, note that `k` is just a sequential number
|
||||
in the array of matched child elements, and has no direct relation to the
|
||||
actual "position" (subtag index) within each `v`'s parent object.
|
||||
|
||||
@function children
|
||||
|
||||
@param var the table (LuaXML object) to work on
|
||||
@tparam ?string tag XML tag to be matched
|
||||
@tparam ?string key attribute key to be matched
|
||||
@param value (optional) attribute value to be matched
|
||||
|
||||
@tparam ?number maxdepth
|
||||
maximum depth allowed, defaults to 1 (only immediate children).
|
||||
You can pass 0 or `true` to iterate _all_ children recursively.
|
||||
|
||||
@return Lua iterator function and initial state (Lua-internal use) - suitable
|
||||
for a `for` loop
|
||||
|
||||
@see match
|
||||
|
||||
@usage
|
||||
local xml = require("LuaXML")
|
||||
local foobar = xml.eval('<foo><a /><b bar="no" /><c bar="yes" /><a /></foo>')
|
||||
|
||||
-- iterate over those children that have a "bar" attribute:
|
||||
for k, v in foobar:children(nil, "bar") do
|
||||
print(k, v:tag(), v.bar)
|
||||
end
|
||||
-- will print
|
||||
-- 1 b no
|
||||
-- 2 c yes
|
||||
|
||||
-- require "bar" to be "yes":
|
||||
for k, v in foobar:children(nil, "bar", "yes") do
|
||||
print(k, v:tag(), v.bar)
|
||||
end
|
||||
-- will print
|
||||
-- 1 c yes
|
||||
|
||||
-- iterate "a" tags: (the first and fourth child will match)
|
||||
for k, v in foobar:children("a") do
|
||||
print(k, v:tag(), v.bar)
|
||||
end
|
||||
-- will print
|
||||
-- 1 a nil
|
||||
-- 2 a nil
|
||||
|
||||
]]
|
||||
function _M.children(var, tag, key, value, maxdepth)
|
||||
|
||||
local function get_children(var, tag, key, value, maxdepth)
|
||||
-- pass maxdepth = 1 to retrieve only immediate child nodes
|
||||
local result = {}
|
||||
_M.iterate(var,
|
||||
function(node, depth)
|
||||
-- add matching node to result table
|
||||
if depth > 0 then table.insert(result, node); end
|
||||
end,
|
||||
tag, key, value, true, maxdepth)
|
||||
return result
|
||||
end
|
||||
|
||||
local function child_iterator(matched, k)
|
||||
k = (k or 0) + 1
|
||||
local v = matched[k]
|
||||
return v and k, v -- key/value pair from matches, or `nil` if no value
|
||||
end
|
||||
|
||||
maxdepth = maxdepth or 1 -- default to 1...
|
||||
-- ...but enumerate all children if it was set to 0 or `true`
|
||||
if maxdepth == 0 or maxdepth == true then maxdepth = nil; end
|
||||
|
||||
-- our "invariant state" will be a table of matched children
|
||||
return child_iterator,
|
||||
get_children(var, tag, key, value, maxdepth)
|
||||
end
|
||||
|
||||
return _M -- return module (table)
|
||||
|
1804
src/third_party/LuaXML_lib.c
vendored
1804
src/third_party/LuaXML_lib.c
vendored
File diff suppressed because it is too large
Load Diff
29
src/third_party/LuaXML_lib.h
vendored
Normal file
29
src/third_party/LuaXML_lib.h
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef LUAXML_LIB_H
|
||||
#define LUAXML_LIB_H
|
||||
|
||||
#ifndef LUAXML_DEBUG
|
||||
# define LUAXML_DEBUG 0 /* set to 1 to enable debugging output */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
|
||||
#if defined __WIN32__ || defined WIN32
|
||||
# include <windows.h>
|
||||
# define _EXPORT __declspec(dllexport)
|
||||
#else
|
||||
# define _EXPORT
|
||||
#endif
|
||||
|
||||
int _EXPORT luaopen_LuaXML_lib (lua_State* L);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // LUAXML_LIB_H
|
@ -34,13 +34,14 @@ htmlEscape = { "☺", "☻", "♥", "♦", "♣", "&
|
||||
htmlEscape[0] = "·" -- in this table, we use a 8 bit character set, where every has a different graphical representation
|
||||
|
||||
-- the conversion table should work as a conversion function for strings as well
|
||||
setmetatable(htmlEscape, {__call = function (tab,str) return string.gsub(str, ".", function (c) return tab[c:byte()] end) end})
|
||||
setmetatable(htmlEscape, {__call = function (tab,str) return string.gsub(str, ".", function (c) return (tab[c:byte()]) end) end})
|
||||
|
||||
|
||||
function htmlEsc(txt)
|
||||
s = txt:gsub("%&", "&")
|
||||
s = s:gsub("%<", "<")
|
||||
return s:gsub("%>", ">")
|
||||
s = s:gsub("%>", ">")
|
||||
return (s)
|
||||
end
|
||||
|
||||
|
||||
|
@ -10,9 +10,20 @@ The following features are available:
|
||||
<ul>
|
||||
]])
|
||||
|
||||
demo_data = {}
|
||||
|
||||
function print_if_available(tab, name)
|
||||
if tab then
|
||||
mg.write("<li>" .. name .. " available</li>\n")
|
||||
if type(tab)=="table" then
|
||||
demo_data[name] = {}
|
||||
demo_data[name][0] = name
|
||||
for nname,nval in pairs(tab) do
|
||||
demo_data[name][nname] = type(nval)
|
||||
end
|
||||
else
|
||||
demo_data[name] = type(tab)
|
||||
end
|
||||
else
|
||||
mg.write("<li>" .. name .. " not available</li>\n")
|
||||
end
|
||||
@ -46,8 +57,12 @@ for _,n in ipairs(libs) do
|
||||
print_if_available(_G[n], n);
|
||||
end
|
||||
mg.write("</ul>\n")
|
||||
print_if_available(sqlite3, "sqlite3 binding")
|
||||
print_if_available(lfs, "lua file system")
|
||||
print_if_available(sqlite3, "SQLite3 binding (sqlite3)")
|
||||
print_if_available(lfs, "LuaFileSystem (lfs)")
|
||||
print_if_available(json, "JSON binding (json)")
|
||||
print_if_available(xml, "LuaXML (xml)")
|
||||
print_if_available(shared, "Lua shared data (shared)")
|
||||
|
||||
|
||||
--recurse(_G)
|
||||
|
||||
@ -122,9 +137,52 @@ else
|
||||
mg.write("</ul>\n")
|
||||
mg.write(string.format("<ul>%u files total</ul>\n", cnt))
|
||||
end
|
||||
mg.write("</p>\n")
|
||||
|
||||
|
||||
function htmlEsc(txt)
|
||||
s = txt:gsub("%&", "&")
|
||||
s = s:gsub("%<", "<")
|
||||
s = s:gsub("%>", ">")
|
||||
return (s)
|
||||
end
|
||||
|
||||
|
||||
function printTable(tab, indent)
|
||||
indent = indent or 0
|
||||
for k,v in pairs(tab) do
|
||||
if (type(v)=="table") then
|
||||
mg.write(string.rep(" ", indent) .. tostring(k) .. ":\n")
|
||||
printTable(v, indent + 1)
|
||||
else
|
||||
mg.write(string.rep(" ", indent) .. tostring(k) .. "\t" .. v .. "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- xml test
|
||||
if (xml) then
|
||||
mg.write("\n<hr/>\n")
|
||||
mg.write("<p>xml2lua:<br>\n<pre>\n");
|
||||
xmlstr = [[<obj attr="a"><sub1 attr="suba">sub1val</sub1><sub2 attr="suba2" /><sub3></sub3><sub4><subsub>subsubval</subsub></sub4></obj>]]
|
||||
xmlev = xml.eval(xmlstr)
|
||||
mg.write(htmlEsc(xmlstr))
|
||||
mg.write("\n-->\n")
|
||||
mg.write(type(xmlev) .. ":\n")
|
||||
mg.write(printTable(xmlev, 1))
|
||||
mg.write("</pre>\n</p>\n")
|
||||
|
||||
mg.write("<p>lua2xml:<br>\n<pre>\n");
|
||||
mg.write(htmlEsc(xml.str(xmlev, 1, "xml")))
|
||||
mg.write("</pre>\n</p>\n")
|
||||
|
||||
mg.write("<p>lua2xml:<br>\n<pre>\n");
|
||||
mg.write(htmlEsc(xml.str(demo_data, 1, "xml")))
|
||||
mg.write("</pre>\n</p>\n")
|
||||
end
|
||||
|
||||
mg.write([[
|
||||
</p>
|
||||
</body></html>
|
||||
]])
|
||||
|
||||
|
@ -166,7 +166,7 @@ mg.write("\r\n")
|
||||
|
||||
-- random
|
||||
mg.write("Random numbers:\r\n")
|
||||
for i=1,10 do mg.write(string.format("%18u\r\n", mg.random())) end
|
||||
for i=1,10 do mg.write(string.format("%18.0f\r\n", mg.random())) end
|
||||
mg.write("\r\n")
|
||||
|
||||
-- uuid
|
||||
|
Loading…
x
Reference in New Issue
Block a user