summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/lxml-xml.lua
diff options
context:
space:
mode:
authorMojca Miklavec <mojca.miklavec@gmail.com>2012-05-14 17:38:55 +0000
committerMojca Miklavec <mojca.miklavec@gmail.com>2012-05-14 17:38:55 +0000
commit15995e10bfc68edf79970c4ea4fbb6678566c46e (patch)
tree2de7ca2a83f2d37ef043ad7429a5cb945bb79ddb /Master/texmf-dist/tex/context/base/lxml-xml.lua
parentc9a39f716f1e5ec820ed3aab2c9aef25c5a9d730 (diff)
ConTeXt 2012.05.14 16:00
git-svn-id: svn://tug.org/texlive/trunk@26371 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/lxml-xml.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-xml.lua287
1 files changed, 180 insertions, 107 deletions
diff --git a/Master/texmf-dist/tex/context/base/lxml-xml.lua b/Master/texmf-dist/tex/context/base/lxml-xml.lua
index 89fcba871bd..7e7922cfb25 100644
--- a/Master/texmf-dist/tex/context/base/lxml-xml.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-xml.lua
@@ -6,15 +6,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -28,16 +30,21 @@ local function all(collected)
return collected
end
---~ local function reverse(collected)
---~ if collected then
---~ local reversed, r = { }, 0
---~ for c=#collected,1,-1 do
---~ r = r + 1
---~ reversed[r] = collected[c]
---~ end
---~ return reversed
---~ end
---~ end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -54,34 +61,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -92,7 +102,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -110,108 +120,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -266,14 +337,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -281,6 +352,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -289,8 +362,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter