diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/lxml-ini.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/lxml-ini.lua | 1138 |
1 files changed, 0 insertions, 1138 deletions
diff --git a/Master/texmf-dist/tex/context/base/lxml-ini.lua b/Master/texmf-dist/tex/context/base/lxml-ini.lua deleted file mode 100644 index 0c40a4bafb9..00000000000 --- a/Master/texmf-dist/tex/context/base/lxml-ini.lua +++ /dev/null @@ -1,1138 +0,0 @@ -if not modules then modules = { } end modules ['lxml-ini'] = { - version = 1.001, - comment = "companion to lxml-ini.tex", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local utf = unicode.utf8 - -local texsprint, texprint, utfchar = tex.sprint or print, tex.print or print, utf.char -local format, concat, insert, remove = string.format, table.concat, table.insert, table.remove -local type, next, tonumber = type, next, tonumber - -local ctxcatcodes = tex.ctxcatcodes -local texcatcodes = tex.texcatcodes -local vrbcatcodes = tex.vrbcatcodes - -local trace_setups = false trackers.register("lxml.setups", function(v) trace_setups = v end) -local trace_loading = false trackers.register("lxml.loading", function(v) trace_loading = v end) - --- for the moment here - -function table.insert_before_value(t,value,extra) - for i=1,#t do - if t[i] == extra then - remove(t,i) - end - end - for i=1,#t do - if t[i] == value then - insert(t,i,extra) - return - end - end - insert(t,1,extra) -end - -function table.insert_after_value(t,value,extra) - for i=1,#t do - if t[i] == extra then - remove(t,i) - end - end - for i=1,#t do - if t[i] == value then - insert(t,i+1,extra) - return - end - end - insert(t,#t+1,extra) -end - --- todo: speed up: remember last index/match combination - -local traverse, lpath = xml.traverse, xml.lpath - -local xmlfilter, xmlfirst, xmllast, xmlall = xml.filter, xml.first, xml.last, xml.all -local xmlcollect, xmlcontent, xmlcollect_texts, xmlcollect_tags, xmlcollect_elements = xml.collect, xml.content, xml.collect_texts, xml.collect_tags, xml.collect_elements -local xmlattribute, xmlindex = xml.filters.attribute, xml.filters.index -local xmlelements = xml.elements - -document = document or { } -document.xml = document.xml or { } - --- todo: loaded and myself per document so that we can garbage collect buffers - -lxml = lxml or { } -lxml.loaded = { } -lxml.myself = { } -lxml.n = 0 - -local loaded = lxml.loaded -local myself = lxml.myself -local stack = lxml.stack - -lxml.self = myself -- be backward compatible for a while - -local function get_id(id) - return (type(id) == "table" and id) or loaded[id] or myself[tonumber(id)] -- no need for tonumber if we pass without "" -end - -lxml.id = get_id - -function lxml.root(id) - return loaded[id] -end - -do - - xml.specialhandler = xml.specialhandler or { } - - local specialhandler = xml.specialhandler - local serialize = xml.serialize - - local crlf = lpeg.P("\r\n") - local cr = lpeg.P("\r") - local lf = lpeg.P("\n") - local space = lpeg.S(" \t\f\v") - local newline = crlf + cr + lf - local spacing = newline * space^0 - local content = lpeg.C((1-spacing)^1) - local verbose = lpeg.C((1-(space+newline))^1) - - -- local capture = ( - -- newline^2 * lpeg.Cc("") / texprint + - -- newline * lpeg.Cc(" ") / texsprint + - -- content / texsprint - -- )^0 - - local capture = ( - space^0 * newline^2 * lpeg.Cc("") / texprint + - space^0 * newline * space^0 * lpeg.Cc(" ") / texsprint + - content / texsprint - )^0 - - local forceraw, rawroot = false, nil - - function lxml.startraw() - forceraw = true - end - function lxml.stopraw() - forceraw = false - end - function lxml.rawroot() - return rawroot - end - function lxml.rawpath(rootid) - if rawroot and type(rawroot) == "table" then - local text, path, rp - if not rawroot.dt then - text, path, rp = "text", "", rawroot[0] - else - path, rp = "tree", "", rawroot.__p__ - end - while rp do - local rptg = rp.tg - if rptg then - path = rptg .. "/" .. path - end - rp = rp.__p__ - end - return { rootid, "/" .. path, text } - end - end - - local function sprint(root) - if not root then - --~ rawroot = false - -- quit - else - local tr = type(root) - if tr == "string" then -- can also be result of lpath - --~ rawroot = false - capture:match(root) - elseif tr == "table" then - rawroot = forceraw and root - serialize(root,sprint,nil,nil,specialhandler,forceraw) - end - end - end - - xml.sprint = sprint - - function xml.tprint(root) -- we can move sprint inline - local tr = type(root) - if tr == "table" then - local n = #root - if n == 0 then - sprint("") -- empty element, else no setup triggered (check this! ) - else - for i=1,n do - sprint(root[i]) - end - end - elseif tr == "string" then - sprint(root) - end - end - - function xml.cprint(root) -- content - if not root then ---~ rawroot = false - -- quit - elseif type(root) == 'string' then ---~ rawroot = false - capture:match(root) - else - local rootdt = root.dt - rawroot = forceraw and root - if rootdt then -- the main one - serialize(rootdt,sprint,nil,nil,specialhandler,forceraw) - else -- probably dt - serialize(root,sprint,nil,nil,specialhandler,forceraw) - end - end - end - - -- lines (untested) - - local buffer = { } - - local capture = ( - newline^2 / function() buffer[#buffer+1] = "" end + - newline / function() buffer[#buffer] = buffer[#buffer] .. " " end + - content / function(s) buffer[#buffer] = buffer[#buffer] .. s end - )^0 - - function lines(root) - if not root then ---~ rawroot = false - -- quit - elseif type(root) == 'string' then ---~ rawroot = false - capture:match(root) - elseif next(root) then -- tr == 'table' - rawroot = forceraw and root - serialize(root,lines,forceraw) - end - end - - function xml.lines(root) - buffer = { "" } - lines(root) - return result - end - - -- cdata - - local linecommand = "\\obeyedline" - local spacecommand = "\\obeyedspace" -- "\\strut\\obeyedspace" - local beforecommand = "" - local aftercommand = "" - - local capture = ( - newline / function( ) texsprint(texcatcodes,linecommand,"{}") end + - verbose / function(s) texsprint(vrbcatcodes,s) end + - space / function( ) texsprint(texcatcodes,spacecommand,"{}") end - )^0 - - local function toverbatim(str) - if beforecommand then texsprint(texcatcodes,beforecommand,"{}") end - capture:match(str) - if aftercommand then texsprint(texcatcodes,aftercommand,"{}") end - end - - function lxml.set_verbatim(before,after,obeyedline,obeyedspace) - beforecommand, aftercommand, linecommand, spacecommand = before, after, obeyedline, obeyedspace - end - - function lxml.set_cdata() - specialhandler['@cd@'] = toverbatim - end - - function lxml.reset_cdata() - specialhandler['@cd@'] = nil - end - - -- local capture = (space^0*newline)^0 * capture * (space+newline)^0 * -1 - - local function toverbatim(str) - if beforecommand then texsprint(texcatcodes,beforecommand,"{}") end - -- todo: add this to capture - str = str:gsub("^[ \t]+[\n\r]+","") - str = str:gsub("[ \t\n\r]+$","") - capture:match(str) - if aftercommand then texsprint(texcatcodes,aftercommand,"{}") end - end - - function lxml.verbatim(id,before,after) - local root = get_id(id) - if root then - if before then texsprint(ctxcatcodes,format("%s[%s]",before,root.tg)) end - -- serialize(root.dt,toverbatim,nil,nil,nil,true) -- was root - local t = { } - serialize(root.dt,function(s) t[#t+1] = s end,nil,nil,nil,true) -- was root - toverbatim(table.concat(t,"")) - if after then texsprint(ctxcatcodes,after) end - end - end - function lxml.inlineverbatim(id) - lxml.verbatim(id,"\\startxmlinlineverbatim","\\stopxmlinlineverbatim") - end - function lxml.displayverbatim(id) - lxml.verbatim(id,"\\startxmldisplayverbatim","\\stopxmldisplayverbatim") - end - - local pihandlers = { } - - specialhandler['@pi@'] = function(str) - for i=1,#pihandlers do - pihandlers[i](str) - end - end - - xml.pihandlers = pihandlers - - local kind = lpeg.P("context-") * lpeg.C((1-lpeg.P("-"))^1) * lpeg.P("-directive") - local space = lpeg.S(" \n\r") - local spaces = space^0 - local class = lpeg.C((1-space)^0) - local key = class - local value = lpeg.C(lpeg.P(1-(space * -1))^0) - - local parser = kind * spaces * class * spaces * key * spaces * value - - pihandlers[#pihandlers+1] = function(str) - -- local kind, class, key, value = parser:match(str) - if str then - local a, b, c, d = parser:match(str) - if d then - texsprint(ctxcatcodes,format("\\xmlcontextdirective{%s}{%s}{%s}{%s}",a,b,c,d)) - end - end - end - - -- print(contextdirective("context-mathml-directive function reduction yes ")) - -- print(contextdirective("context-mathml-directive function ")) - - function lxml.main(id) - serialize(get_id(id),sprint,nil,nil,specialhandler) -- the real root (@rt@) - end - - specialhandler['@dt@'] = function() - -- nothing - end - -end - -local xmlsprint = xml.sprint -local xmltprint = xml.tprint - --- redefine xml load - -xml.originalload = xml.originalload or xml.load - -local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming - -function xml.load(filename) - lxml.n = lxml.n + 1 - starttiming(xml) - local xmldata = xml.convert((filename and resolvers.loadtexfile(filename)) or "") - stoptiming(xml) - return xmldata -end - -function lxml.load(id,filename) - lxml.n = lxml.n + 1 - filename = commands.preparedfile(filename) - if trace_loading then - commands.writestatus("lxml","loading file: %s",filename) - end - loaded[id] = xml.load(filename) - return loaded[id], filename -end - -function lxml.register(id,xmltable) - lxml.n = lxml.n + 1 - loaded[id] = xmltable - return xmltable -end - -function lxml.include(id,pattern,attribute,recurse) - starttiming(xml) - xml.include(get_id(id),pattern,attribute,recurse,function(filename) - if filename then - filename = commands.preparedfile(filename) - if trace_loading then - commands.writestatus("lxml","including file: %s",filename) - end - return resolvers.loadtexfile(filename) or "" - else - return "" - end - end) - stoptiming(xml) -end - -function lxml.utfize(id) - xml.utfize(get_id(id)) -end - -function lxml.filter(id,pattern) - xmlsprint(xmlfilter(get_id(id),pattern)) -end -function lxml.first(id,pattern) - xmlsprint(xmlfirst(get_id(id),pattern)) -end -function lxml.last(id,pattern) - xmlsprint(xmllast(get_id(id),pattern)) -end -function lxml.all(id,pattern) - -- xmltprint(xmlcollect(get_id(id),pattern)) - traverse(get_id(id), lpath(pattern), function(r,d,k) - -- to be checked for root:: - if d then - xmlsprint(d[k]) - else -- new, maybe wrong ---~ xmlsprint(r) - end - return false - end) -end - -function lxml.nonspace(id,pattern) -- slow, todo loop - xmltprint(xmlcollect(get_id(id),pattern,true)) -end - ---~ function lxml.content(id) ---~ xmlsprint(xmlcontent(get_id(id)) or "") ---~ end - -function lxml.strip(id,pattern,nolines) - xml.strip(get_id(id),pattern,nolines) -end - -function lxml.text(id,pattern) - xmltprint(xmlcollect_texts(get_id(id),pattern) or {}) -end - -function lxml.tags(id,pattern) - local tags = xmlcollect_tags(get_id(id),pattern) - if tags then - texsprint(concat(tags,",")) - end -end - -function lxml.raw(id,pattern) -- the content, untouched by commands - local c = xmlfilter(get_id(id),pattern) - if c then - xml.serialize(c.dt,texsprint,nil,nil,nil,true) - end -end - -function lxml.snippet(id,i) - local e = get_id(id) - if e then - local edt = e.dt - if edt then - xmlsprint(edt[i]) - end - end -end - -function xml.element(e,n) - if e then - local edt = e.dt - if edt then - if n > 0 then - for i=1,#edt do - local ei = edt[i] - if type(ei) == "table" then - if n == 1 then - xmlsprint(ei) - return - else - n = n - 1 - end - end - end - elseif n < 0 then - for i=#edt,1,-1 do - local ei = edt[i] - if type(ei) == "table" then - if n == -1 then - xmlsprint(ei) - return - else - n = n + 1 - end - end - end - end - end - end -end - -function lxml.element(id,n) - xml.element(get_id(id),n) -end - -function lxml.stripped(id,pattern,nolines) - local str = xmlcontent(get_id(id),pattern) or "" - str = str:gsub("^%s*(.-)%s*$","%1") - if nolines then - str = str:gsub("%s+"," ") - end - xmlsprint(str) -end - -function lxml.flush(id) - id = get_id(id) - local dt = id and id.dt - if dt then - xmlsprint(dt) - end -end - ---~ function lxml.strip(id,flush) ---~ local dt = get_id(id).dt ---~ local str = dt[1] ---~ if type(str) == "string" then ---~ dt[1] = str:gsub("^ *","") ---~ end ---~ str = dt[#dt] ---~ if type(str) == "string" then ---~ dt[#dt] = str:gsub(" *$","") ---~ end ---~ if flush then ---~ xmlsprint(dt) ---~ end ---~ end - -function lxml.direct(id) - xmlsprint(get_id(id)) -end - -function lxml.index(id,pattern,i) - xmlsprint((xmlindex(get_id(id),pattern,i))) -end - -function lxml.attribute(id,pattern,a,default) --todo: snelle xmlatt - local str = xmlattribute(get_id(id),pattern,a) or "" - texsprint((str == "" and default) or str) -end - -function lxml.count(id,pattern) - texsprint(xml.count(get_id(id),pattern) or 0) -end -function lxml.nofelements(id) - local e = get_id(id) - local edt = e.dt - if edt and type(edt) == "table" then - local n = 0 - for i=1,#edt do - if type(edt[i]) == "table" then - n = n + 1 - end - end - texsprint(n) - else - texsprint(0) - end -end -function lxml.name(id) -- or remapped name? -> lxml.info, combine - local r = get_id(id) - local ns = r.rn or r.ns or "" - if ns ~= "" then - texsprint(ns,":",r.tg) - else - texsprint(r.tg) - end -end -function lxml.tag(id) -- tag vs name -> also in l-xml tag->name - texsprint(get_id(id).tg or "") -end -function lxml.namespace(id) -- or remapped name? - local root = get_id(id) - texsprint(root.rn or root.ns or "") -end - ---~ function lxml.concat(id,what,separator,lastseparator) ---~ texsprint(concat(xml.collect_texts(get_id(id),what,true),separator or "")) ---~ end - -function lxml.concatrange(id,what,start,stop,separator,lastseparator) -- test this on mml - local t = xmlcollect_elements(lxml.id(id),what,true) -- ignorespaces - local separator = separator or "" - local lastseparator = lastseparator or separator or "" - start, stop = (start == "" and 1) or tonumber(start) or 1, (stop == "" and #t) or tonumber(stop) or #t - if stop < 0 then stop = #t + stop end -- -1 == last-1 - for i=start,stop do - xmlsprint(t[i]) - if i == #t then - -- nothing - elseif i == #t-1 and lastseparator ~= "" then - texsprint(ctxcatcodes,lastseparator) - elseif separator ~= "" then - texsprint(ctxcatcodes,separator) - end - end -end - -function lxml.concat(id,what,separator,lastseparator) - lxml.concatrange(id,what,false,false,separator,lastseparator) -end - --- string : setup --- true : text (no <self></self>) --- false : ignore --- function : call - --- todo: free self after usage, i.e. after the setup, which --- means a call to lua; we can also choose a proper maximum --- and cycle or maybe free on demand - --- problems with empty elements --- we use a real tex.sprint, else spaces go wrong --- maybe just a .. because this happens often - -function xml.command(root, command) - local tc = type(command) - if tc == "string" then - -- setup - local n = #myself + 1 - myself[n] = root - texsprint(ctxcatcodes,format("\\xmlsetup{%i}{%s}",n,command)) - elseif tc == "function" then - -- function - command(root) - elseif command == true then - -- text (no <self></self>) / so, no mkii fallback then - xmltprint(root.dt) - elseif command == false then - -- ignore - else - -- fuzzy, so ignore too - end -end - -function lxml.setaction(id,pattern,action) - for rt, dt, dk in xmlelements(get_id(id),pattern) do - dt[dk].command = action - end -end - -function lxml.setsetup(id,pattern,setup) - if not setup or setup == "" or setup == "*" or setup == "-" or setup == "+" then - for rt, dt, dk in xmlelements(get_id(id),pattern) do - local dtdk = dt and dt[dk] or rt - local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg - if tg then -- to be sure - local command = (ns == "" and tg) or (ns .. ":" .. tg) - if setup == "-" then - dtdk.command = false - if trace then - logs.report("lxml","lpath matched -> %s -> skipped", command) - end - elseif setup == "+" then - dtdk.command = true - if trace_setups then - logs.report("lxml","lpath matched -> %s -> text", command) - end - else - dtdk.command = command - if trace_setups then - logs.report("lxml","lpath matched -> %s -> %s", command, command) - end - end - end - end - else - local a, b = setup:match("^(.+:)([%*%-])$") - if a and b then - for rt, dt, dk in xmlelements(get_id(id),pattern) do - local dtdk = (dt and dt[dk]) or rt - local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg - if b == "-" then - dtdk.command = false - if trace_setups then - if ns == "" then - logs.report("lxml","lpath matched -> %s -> skipped", tg) - else - logs.report("lxml","lpath matched -> %s:%s -> skipped", ns, tg) - end - end - elseif b == "+" then - dtdk.command = true - if trace_setups then - if ns == "" then - logs.report("lxml","lpath matched -> %s -> text", tg) - else - logs.report("lxml","lpath matched -> %s:%s -> text", ns, tg) - end - end - else - dtdk.command = a .. tg - if trace_setups then - if ns == "" then - logs.report("lxml","lpath matched -> %s -> %s", tg, dtdk.command) - else - logs.report("lxml","lpath matched -> %s:%s -> %s", ns, tg, dtdk.command) - end - end - end - end - else - if trace_setups then - logs.report("lxml","lpath pattern -> %s -> %s", pattern, setup) - end - for rt, dt, dk in xmlelements(get_id(id),pattern) do - local dtdk = (dt and dt[dk]) or rt - dtdk.command = setup - if trace_setups then - local ns, tg = dtdk.rn or dtdk.ns, dtdk.tg - if ns == "" then - logs.report("lxml","lpath matched -> %s -> %s", tg, setup) - else - logs.report("lxml","lpath matched -> %s:%s -> %s", ns, tg, setup) - end - end - end - end - end -end - -function lxml.idx(id,pattern,i) -- hm, hashed, needed? - local r = get_id(id) - if r then - local rp = r.patterns - if not rp then - rp = { } - r.patterns = rp - end - if not rp[pattern] then - rp[pattern] = xmlcollect_elements(r,pattern) -- dd, rr - end - local rpi = rp[pattern] and rp[pattern][i] - if rpi then - xmlsprint(rpi) - end - end -end - -function lxml.info(id) - id = get_id(id) - local ns, tg = id.ns, id.tg - if ns and ns ~= "" then -- best make a function - tg = ns .. ":" .. tg - else - tg = tg or "?" - end - texsprint(tg) -end - - -local function command(root,pattern,cmd) -- met zonder '' - cmd = cmd:gsub("^([\'\"])(.-)%1$", "%2") - traverse(root, lpath(pattern), function(r,d,k) - -- this can become pretty large - local m = (d and d[k]) or r -- brrr this r, maybe away - if type(m) == "table" then -- probably a bug - local n = #myself + 1 - myself[n] = m - texsprint(ctxcatcodes,format("\\xmlsetup{%s}{%s}",n,cmd)) - end - end) -end - -xml.filters.command = command - -function lxml.command(id,pattern,cmd) - command(get_id(id),pattern,cmd) -end - -local function dofunction(root,pattern,fnc) - traverse(root, lpath(pattern), xml.functions[fnc]) -- r, d, t -end - -xml.filters["function"] = dofunction - ---~ <?xml version="1.0" standalone="yes"?> ---~ <!-- demo.cdx --> ---~ <directives> ---~ <!-- ---~ <directive attribute='id' value="100" setup="cdx:100"/> ---~ <directive attribute='id' value="101" setup="cdx:101"/> ---~ --> ---~ <!-- ---~ <directive attribute='cdx' value="colors" element="cals:table" setup="cdx:cals:table:colors"/> ---~ <directive attribute='cdx' value="vertical" element="cals:table" setup="cdx:cals:table:vertical"/> ---~ <directive attribute='cdx' value="noframe" element="cals:table" setup="cdx:cals:table:noframe"/> ---~ --> ---~ <directive attribute='cdx' value="*" element="cals:table" setup="cdx:cals:table:*"/> ---~ </directives> - -lxml.directives = { } - -local data = { - setup = { }, - before = { }, - after = { } -} - -function lxml.directives.load(filename) - local fullname = resolvers.find_file(filename) or "" - if fullname ~= "" then - filename = fullname - end - local root = xml.load(filename) - for r, d, k in xmlelements(root,"directive") do - local dk = d[k] - local at = dk.at - local attribute, value, element = at.attribute or "", at.value or "", at.element or '*' - local setup, before, after = at.setup or "", at.before or "", at.after or "" - if attribute ~= "" and value ~= "" then - local key = format("%s::%s::%s",element,attribute,value) - local t = data[key] or { } - if setup ~= "" then t.setup = setup end - if before ~= "" then t.before = before end - if after ~= "" then t.after = after end - data[key] = t - end - end -end - -function lxml.directives.setup(root,attribute,element) - lxml.directives.handle_setup('setup',root,attribute,element) -end -function lxml.directives.before(root,attribute,element) - lxml.directives.handle_setup('before',root,attribute,element) -end -function lxml.directives.after(root,attribute,element) - lxml.directives.handle_setup('after',root,attribute,element) -end - -function lxml.directives.handle_setup(category,root,attribute,element) - root = get_id(root) - attribute = attribute - if attribute then - local value = root.at[attribute] - if value then - if not element then - local ns, tg = root.rn or root.ns, root.tg - if ns == "" then - element = tg - else - element = ns .. ':' .. tg - end - end - local setup = data[format("%s::%s::%s",element,attribute,value)] - if setup then - setup = setup[category] - end - if setup then - texsprint(ctxcatcodes,format("\\directsetup{%s}",setup)) - else - setup = data[format("%s::%s::*",element,attribute)] - if setup then - setup = setup[category] - end - if setup then - texsprint(ctxcatcodes,format("\\directsetup{%s}",setup:gsub('%*',value))) - end - end - end - end -end - -function xml.getbuffer(name) -- we need to make sure that commands are processed - if not name or name == "" then - name = tex.jobname - end - xml.tostring(xml.convert(concat(buffers.data[name] or {},""))) -end - -function lxml.loadbuffer(id,name) - if not name or name == "" then - name = tex.jobname - end - starttiming(xml) - loaded[id] = xml.convert(buffers.collect(name or id,"\n")) - stoptiming(xml) - return loaded[id], name or id -end - -function lxml.loaddata(id,str) - starttiming(xml) - loaded[id] = xml.convert(str or "") - stoptiming(xml) - return loaded[id], id -end - -function lxml.loadregistered(id) - return loaded[id], id -end - --- for the moment here: - -lxml.set_verbatim("\\xmlcdatabefore", "\\xmlcdataafter", "\\xmlcdataobeyedline", "\\xmlcdataobeyedspace") -lxml.set_cdata() - -local traced = { } - -function lxml.trace_text_entities(str) - return str:gsub("&(.-);",function(s) - traced[s] = (traced[s] or 0) + 1 - return "["..s.."]" - end) -end - -function lxml.show_text_entities() - for k,v in ipairs(table.sortedkeys(traced)) do - local h = v:match("^#x(.-)$") - if h then - local d = tonumber(h,16) - local u = utfchar(d) - logs.report("lxml","entity: %s / %s / %s / n=%s",h,d,u,traced[v]) - else - logs.report("lxml","entity: %s / n=%s",v,traced[v]) - end - end -end - -local error_entity_handler = function(s) return format("[%s]",s) end -local element_entity_handler = function(s) return format("<ctx:e n='%s'/>",s) end - -function lxml.set_mkii_entityhandler() - xml.entity_handler = error_entity_handler - xml.set_text_cleanup() -end -function lxml.set_mkiv_entityhandler() - xml.entity_handler = element_entity_handler - xml.set_text_cleanup(xml.resolve_text_entities) -end -function lxml.reset_entityhandler() - xml.entity_handler = error_entity_handler - xml.set_text_cleanup() -end - -local function with_elements_only(e,handle) - if e and handle then - local etg = e.tg - if etg then - if e.special and etg ~= "@rt@" then - if resthandle then - resthandle(e) - end - else - local edt = e.dt - if edt then - for i=1,#edt do - local e = edt[i] - if type(e) == "table" then - handle(e) - with_elements_only(e,handle) - end - end - end - end - end - end -end - - local function with_elements_only(e,handle,depth) - if e and handle then - local edt = e.dt - if edt then - depth = depth or 0 - for i=1,#edt do - local e = edt[i] - if type(e) == "table" then - handle(e,depth) - with_elements_only(e,handle,depth+1) - end - end - end - end -end - -xml.with_elements_only = with_elements_only - -local function to_text(e) - if e.command == nil then - local etg = e.tg - if etg and e.special and etg ~= "@rt@" then - e.command = false -- i.e. skip - else - e.command = true -- i.e. no <self></self> - end - end -end -local function to_none(e) - if e.command == nil then - e.command = false -- i.e. skip - end -end - --- can be made faster: just recurse over whole table, todo - -function lxml.set_command_to_text(id) - xml.with_elements_only(get_id(id),to_text) -end - -function lxml.set_command_to_none(id) - xml.with_elements_only(get_id(id),to_none) -end - -function lxml.get_command_status(id) - local status, stack = {}, {} - local function get(e,d) - local ns, tg = e.ns, e.tg - local name = tg - if ns ~= "" then name = ns .. ":" .. tg end - stack[d] = name - local ec = e.command - if ec == true then - ec = "system: text" - elseif ec == false then - ec = "system: skip" - elseif ec == nil then - ec = "system: not set" - elseif type(ec) == "string" then - ec = "setup: " .. ec - else -- function - ec = tostring(ec) - end - local tag = table.concat(stack," => ",1,d) - local s = status[tag] - if not s then - s = { } - status[tag] = s - end - s[ec] = (s[ec] or 0) + 1 - end - if id then - xml.with_elements_only(get_id(id),get) - return status - else - local t = { } - for id, _ in pairs(loaded) do - t[id] = lxml.get_command_status(id) - end - return t - end -end - -local setups = { } - -function lxml.installsetup(what,document,setup,where) - document = document or "*" - local sd = setups[document] - if not sd then sd = { } setups[document] = sd end - for k=1,#sd do - if sd[k] == setup then sd[k] = nil break end - end - if what == 1 then - if trace_loading then - commands.writestatus("lxml","prepending setup %s for %s",setup,document) - end - insert(sd,1,setup) - elseif what == 2 then - if trace_loading then - commands.writestatus("lxml","appending setup %s for %s",setup,document) - end - insert(sd,setup) - elseif what == 3 then - if trace_loading then - commands.writestatus("lxml","inserting setup %s for %s before %s",setup,document,where) - end - table.insert_before_value(sd,setup,where) - elseif what == 4 then - if trace_loading then - commands.writestatus("lxml","inserting setup %s for %s after %s",setup,document,where) - end - table.insert_after_value(sd,setup,where) - end -end - -function lxml.flushsetups(...) - local done = { } - for _, document in ipairs({...}) do - local sd = setups[document] - if sd then - for k=1,#sd do - local v= sd[k] - if not done[v] then - if trace_loading then - commands.writestatus("lxml","applying setup %02i = %s to %s",k,v,document) - end - texsprint(ctxcatcodes,format("\\directsetup{%s}",v)) - done[v] = true - end - end - elseif trace_loading then - commands.writestatus("lxml","no setups for %s",document) - end - end -end - -function lxml.resetsetups(document) - if trace_loading then - commands.writestatus("lxml","resetting all setups for %s",document) - end - setups[document] = { } -end - -function lxml.removesetup(document,setup) - local s = setups[document] - if s then - for i=1,#s do - if s[i] == setup then - if trace_loading then - commands.writestatus("lxml","removing setup %s for %s",setup,document) - end - remove(t,i) - break - end - end - end -end - -local found, isempty = xml.found, xml.isempty - -function lxml.doif (id,pattern) commands.doif (found(get_id(id),pattern,false)) end -function lxml.doifnot (id,pattern) commands.doifnot (found(get_id(id),pattern,false)) end -function lxml.doifelse (id,pattern) commands.doifelse(found(get_id(id),pattern,false)) end - --- todo: if no second arg or second arg == "" then quick test - -function lxml.doiftext (id,pattern) commands.doif (found (get_id(id),pattern,true)) end -function lxml.doifnottext (id,pattern) commands.doifnot (found (get_id(id),pattern,true)) end -function lxml.doifelsetext (id,pattern) commands.doifelse(found (get_id(id),pattern,true)) end - --- special case: "*" and "" -> self else lpath lookup - -function lxml.doifelseempty(id,pattern) commands.doifelse(isempty(get_id(id),pattern ~= "" and pattern ~= nil)) end -- not yet done, pattern - --- status info - -statistics.register("xml load time", function() - local n = lxml.n - if n > 0 then - local stats = xml.statistics() - return format("%s seconds, lpath calls: %s, cached calls: %s", statistics.elapsedtime(xml), stats.lpathcalls, stats.lpathcached) - else - return nil - end -end) - -statistics.register("lxml load time", function() - local n = #lxml.self - if n > 0 then - return format("%s seconds preparation, backreferences: %i", statistics.elapsedtime(lxml),n) - else - return nil - end -end) |