lxml-mis.lua /size: 3574 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['lxml-mis'] = {
2    version   = 1.001,
3    comment   = "this module is the basis for the lxml-* ones",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local xml, lpeg, string = xml, lpeg, string
10
11local type = type
12local concat = table.concat
13local format, gsub, match = string.format, string.gsub, string.match
14local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
15local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Cs
16
17lpegpatterns.xml  = lpegpatterns.xml or { }
18local xmlpatterns = lpegpatterns.xml
19
20--[[ldx--
21<p>The following helper functions best belong to the <t>lxml-ini</t>
22module. Some are here because we need then in the <t>mk</t>
23document and other manuals, others came up when playing with
24this module. Since this module is also used in <l n='mtxrun'/> we've
25put them here instead of loading mode modules there then needed.</p>
26--ldx]]--
27
28local function xmlgsub(t,old,new) -- will be replaced
29    local dt = t.dt
30    if dt then
31        for k=1,#dt do
32            local v = dt[k]
33            if type(v) == "string" then
34                dt[k] = gsub(v,old,new)
35            else
36                xmlgsub(v,old,new)
37            end
38        end
39    end
40end
41
42-- xml.gsub = xmlgsub
43
44function xml.stripleadingspaces(dk,d,k) -- cosmetic, for manual
45    if d and k then
46        local dkm = d[k-1]
47        if dkm and type(dkm) == "string" then
48            local s = match(dkm,"\n(%s+)")
49            xmlgsub(dk,"\n"..rep(" ",#s),"\n")
50        end
51    end
52end
53
54-- xml.escapes   = { ['&'] = '&amp;', ['<'] = '&lt;', ['>'] = '&gt;', ['"'] = '&quot;' }
55-- xml.unescapes = { } for k,v in next, xml.escapes do xml.unescapes[v] = k end
56
57-- function xml.escaped  (str) return (gsub(str,"(.)"   , xml.escapes  )) end
58-- function xml.unescaped(str) return (gsub(str,"(&.-;)", xml.unescapes)) end
59-- function xml.cleansed (str) return (gsub(str,"<.->"  , ''           )) end -- "%b<>"
60
61-- 100 * 2500 * "oeps< oeps> oeps&" : gsub:lpeg|lpeg|lpeg
62--
63-- 1021:0335:0287:0247
64
65-- 10 * 1000 * "oeps< oeps> oeps& asfjhalskfjh alskfjh alskfjh alskfjh ;al J;LSFDJ"
66--
67-- 1559:0257:0288:0190 (last one suggested by roberto)
68
69----- escaped = Cs((S("<&>") / xml.escapes + 1)^0)
70----- escaped = Cs((S("<")/"&lt;" + S(">")/"&gt;" + S("&")/"&amp;" + 1)^0)
71local normal  = (1 - S("<&>"))^0
72local special = P("<")/"&lt;" + P(">")/"&gt;" + P("&")/"&amp;"
73local escaped = Cs(normal * (special * normal)^0)
74
75-- 100 * 1000 * "oeps&lt; oeps&gt; oeps&amp;" : gsub:lpeg == 0153:0280:0151:0080 (last one by roberto)
76
77local normal    = (1 - S"&")^0
78local special   = P("&lt;")/"<" + P("&gt;")/">" + P("&amp;")/"&"
79local unescaped = Cs(normal * (special * normal)^0)
80
81-- 100 * 5000 * "oeps <oeps bla='oeps' foo='bar'> oeps </oeps> oeps " : gsub:lpeg == 623:501 msec (short tags, less difference)
82
83local cleansed = Cs(((P("<") * (1-P(">"))^0 * P(">"))/"" + 1)^0)
84
85xmlpatterns.escaped   = escaped
86xmlpatterns.unescaped = unescaped
87xmlpatterns.cleansed  = cleansed
88
89function xml.escaped  (str) return lpegmatch(escaped,str)   end
90function xml.unescaped(str) return lpegmatch(unescaped,str) end
91function xml.cleansed (str) return lpegmatch(cleansed,str)  end
92
93-- this might move
94
95function xml.fillin(root,pattern,str,check)
96    local e = xml.first(root,pattern)
97    if e then
98        local n = #e.dt
99        if not check or n == 0 or (n == 1 and e.dt[1] == "") then
100            e.dt = { str }
101        end
102    end
103end
104