From 891d790aa1dafff5340c181e3dce3332526e4834 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 13 Aug 2012 22:41:51 +0000 Subject: new luatex package luaxml (13aug12) git-svn-id: svn://tug.org/texlive/trunk@27394 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/luatex/luaxml/README | 27 + Master/texmf-dist/doc/luatex/luaxml/luaxml.pdf | Bin 0 -> 111453 bytes Master/texmf-dist/doc/luatex/luaxml/luaxml.tex | 355 +++++++++++++ .../tex/luatex/luaxml/luaxml-mod-handler.lua | 338 +++++++++++++ .../tex/luatex/luaxml/luaxml-mod-xml.lua | 547 +++++++++++++++++++++ .../tex/luatex/luaxml/luaxml-selectors.lua | 42 ++ .../texmf-dist/tex/luatex/luaxml/luaxml-stack.lua | 63 +++ Master/tlpkg/bin/tlpkg-ctan-check | 2 +- Master/tlpkg/libexec/ctan2tds | 1 + Master/tlpkg/tlpsrc/collection-luatex.tlpsrc | 1 + Master/tlpkg/tlpsrc/luaxml.tlpsrc | 0 11 files changed, 1375 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/luatex/luaxml/README create mode 100644 Master/texmf-dist/doc/luatex/luaxml/luaxml.pdf create mode 100644 Master/texmf-dist/doc/luatex/luaxml/luaxml.tex create mode 100644 Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-handler.lua create mode 100644 Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-xml.lua create mode 100644 Master/texmf-dist/tex/luatex/luaxml/luaxml-selectors.lua create mode 100644 Master/texmf-dist/tex/luatex/luaxml/luaxml-stack.lua create mode 100644 Master/tlpkg/tlpsrc/luaxml.tlpsrc diff --git a/Master/texmf-dist/doc/luatex/luaxml/README b/Master/texmf-dist/doc/luatex/luaxml/README new file mode 100644 index 00000000000..cb48cbab9bd --- /dev/null +++ b/Master/texmf-dist/doc/luatex/luaxml/README @@ -0,0 +1,27 @@ +Introduction +============ + +LuaXML is pure lua library for reading and serializing of the XML files. Current release is aimed mainly as support +for the odsfile package. The documentation was created by automatic conversion of original documentation in the source code. +In this version, some files not useful for luaTeX were droped. Original files can be found at + + http://manoelcampos.com/files/LuaXML--0.0.0-lua5.1.tgz + + +License: +======== + +This code is freely distributable under the terms of the Lua license + (http://www.lua.org/copyright.html) + + +Author +------ +Michal Hoftich +Email: michal.h21@gmail.com + +Original authors: Paul Chakravarti and Manoel Campos (http://manoelcampos.com) + +If you are interested in the process of development you may observe + + https://github.com/michal-h21/LuaXML \ No newline at end of file diff --git a/Master/texmf-dist/doc/luatex/luaxml/luaxml.pdf b/Master/texmf-dist/doc/luatex/luaxml/luaxml.pdf new file mode 100644 index 00000000000..cddfdcdf5d9 Binary files /dev/null and b/Master/texmf-dist/doc/luatex/luaxml/luaxml.pdf differ diff --git a/Master/texmf-dist/doc/luatex/luaxml/luaxml.tex b/Master/texmf-dist/doc/luatex/luaxml/luaxml.tex new file mode 100644 index 00000000000..34363fbcf04 --- /dev/null +++ b/Master/texmf-dist/doc/luatex/luaxml/luaxml.tex @@ -0,0 +1,355 @@ +\documentclass{ltxdoc} +\usepackage{tgschola,url} +\usepackage[english]{babel} +\begin{document} + \title{The \textsc{LuaXML} library} + \author{Paul Chakravarti \and Michal Hoftich} + \maketitle +\tableofcontents +\section*{Introduction} + +|LuaXML| is pure lua library for reading and serializing of the |xml| files. +Current release is aimed mainly as support for the odsfile package. +In first release it was included with the odsfile package, +but as it is general library which can be used also with other packages, +I decided to distribute it as separate library. + +\noindent Example of usage: + +\begin{verbatim} +xml = require('luaxml-mod-xml') +handler = require('luaxml-mod-handler') +\end{verbatim} + +First load the libraries. In |luaxml-mod-xml|, there is xml parser and also serializer. In |luaxml-mod-handler|, there are various handlers for dealing with xml data. Handlers are objects with callback functions which are invoked for every type of content in the |xml| file. More information about handlers can be found in the original documentation, section \ref{sec:handlers}. +\begin{verbatim} +sample = [[ + + hello + world. + another +]] +treehandler = handler.simpleTreeHandler() +x = xml.xmlParser(treehandler) +x:parse(sample) +\end{verbatim} + +You have to create handler object, using |handler.simpleTreeHandler()| and xml parser object using |xml.xmlParser(handler object)|. |simpleTreehandler| creates simple table hierarchy, with top root node in |treehandler.root| +\begin{verbatim} +-- pretty printing function +function printable(tb, level) + level = level or 1 + local spaces = string.rep(' ', level*2) + for k,v in pairs(tb) do + if type(v) ~= "table" then + print(spaces .. k..'='..v) + else + print(spaces .. k) + level = level + 1 + printable(v, level) + end + end +end + +-- print table +printable(treehandler.root) +-- print xml serialization of table +print(xml.serialize(treehandler.root)) +-- direct access to the element +print(treehandler.root["a"]["b"][1]) + +-- output: +-- a +-- d=hello +-- b +-- 1=world. +-- 2 +-- 1=another +-- _attr +-- at=Hi +-- +-- +-- hello +-- world. +-- +-- another +-- +-- +-- +-- world. +\end{verbatim} + +Note that |simpleTreeHandler| creates tables that can be easily accessed using standard lua functions, but in case of mixed content, like +\begin{verbatim} +hello + world + +\end{verbatim} +it produces wrong results. It is useful mostly for data |xml| files, not for text formats like |xhtml|. + +Because at the moment it is intended mainly as support for the odsfile package, there is little documentation, +what follows is the original documentation of |LuaXML|, which may be little bit obsolete now. + +\clearpage +\noindent{\Huge Original documentation} +\medskip + +\noindent This document was created automatically from original source code comments using Pandoc\footnote{\url{http://johnmacfarlane.net/pandoc/}} + +\section{Overview} + + +This module provides a non-validating XML stream parser in Lua. +\section{Features} + +\begin{itemize} +\item + Tokenises well-formed XML (relatively robustly) +\item + Flexible handler based event api (see below) +\item + Parses all XML Infoset elements - ie. + \begin{itemize} + \item + Tags + \item + Text + \item + Comments + \item + CDATA + \item + XML Decl + \item + Processing Instructions + \item + DOCTYPE declarations + \end{itemize} +\item + Provides limited well-formedness checking (checks for basic syntax \& + balanced tags only) +\item + Flexible whitespace handling (selectable) +\item + Entity Handling (selectable) +\end{itemize} +\section{Limitations} + +\begin{itemize} +\item + Non-validating +\item + No charset handling +\item + No namespace support +\item + Shallow well-formedness checking only (fails to detect most semantic + errors) +\end{itemize} +\section{API} + +The parser provides a partially object-oriented API with functionality +split into tokeniser and hanlder components. + +The handler instance is passed to the tokeniser and receives callbacks +for each XML element processed (if a suitable handler function is +defined). The API is conceptually similar to the SAX API but implemented +differently. + +The following events are generated by the tokeniser + +\begin{verbatim} +handler:start - Start Tag +handler:end - End Tag +handler:text - Text +handler:decl - XML Declaration +handler:pi - Processing Instruction +handler:comment - Comment +handler:dtd - DOCTYPE definition +handler:cdata - CDATA +\end{verbatim} +The function prototype for all the callback functions is + +\begin{verbatim} +callback(val,attrs,start,end) +\end{verbatim} +where attrs is a table and val/attrs are overloaded for specific +callbacks - ie. + +\begin{tabular}{llp{5cm}} +Callback & val & attrs (table)\\ +\hline +start & name & |{ attributes (name=val).. }|\\ +end & name & nil\\ +text & || & nil\\ +cdata & | | & nil\\ +decl & "xml" & |{ attributes (name=val).. }|\\ +pi & pi name & \begin{verbatim}{ attributes (if present).. + _text = +}\end{verbatim}\\ +comment & || & nil\\ +dtd & root element & \begin{verbatim}{ _root = , + _type = SYSTEM|PUBLIC, + _name = , + _uri = , + _internal = +}\end{verbatim}\\ +\end{tabular} + +(start \& end provide the character positions of the start/end of the +element) + +XML data is passed to the parser instance through the `parse' method +(Nore: must be passed a single string currently) + +\section{Options} + +Parser options are controlled through the `self.options' table. +Available options are - + +\begin{itemize} +\item + stripWS + + Strip non-significant whitespace (leading/trailing) and do not + generate events for empty text elements +\item + expandEntities + + Expand entities (standard entities + single char numeric entities only + currently - could be extended at runtime if suitable DTD parser added + elements to table (see obj.\_ENTITIES). May also be possible to expand + multibyre entities for UTF--8 only +\item + errorHandler + + Custom error handler function +\end{itemize} +NOTE: Boolean options must be set to `nil' not `0' + +\section{Usage} + +Create a handler instance - + +\begin{verbatim} +h = { start = function(t,a,s,e) .... end, + end = function(t,a,s,e) .... end, + text = function(t,a,s,e) .... end, + cdata = text } +\end{verbatim} +(or use predefined handler - see luaxml-mod-handler.lua) + +Create parser instance - + +\begin{verbatim} +p = xmlParser(h) +\end{verbatim} +Set options - + +\begin{verbatim} +p.options.xxxx = nil +\end{verbatim} +Parse XML data - + +\begin{verbatim} +xmlParser:parse(", + _type = ROOT|ELEMENT|TEXT|COMMENT|PI|DECL|DTD, + _attr = { Node attributes - see callback API }, + _parent = + _children = { List of child nodes - ROOT/NODE only } + } + +\end{verbatim} +The dom structure is capable of representing any valid XML document +\subsubsection{simpleTreeHandler} + +simpleTreeHandler is a simplified handler which attempts to generate a +more `natural' table based structure which supports many common XML +formats. + +The XML tree structure is mapped directly into a recursive table +structure with node names as keys and child elements as either a table +of values or directly as a string value for text. Where there is only a +single child element this is inserted as a named key - if there are +multiple elements these are inserted as a vector (in some cases it may +be preferable to always insert elements as a vector which can be +specified on a per element basis in the options). Attributes are +inserted as a child element with a key of `\_attr'. + +Only Tag/Text \& CDATA elements are processed - all others are ignored. + +This format has some limitations - primarily + +\begin{itemize} +\item Mixed-Content behaves unpredictably - the relationship between text + elements and embedded tags is lost and multiple levels of mixed + content does not work +\item If a leaf element has both a text element and attributes then the text + must be accessed through a vector (to provide a container for the + attribute) +\end{itemize} +In general however this format is relatively useful. + + +\subsection{Options} + +\begin{verbatim} +simpleTreeHandler.options.noReduce = { = bool,.. } + + - Nodes not to reduce children vector even if only + one child + +domHandler.options.(comment|pi|dtd|decl)Node = bool + + - Include/exclude given node types +\end{verbatim} +\subsection{Usage} + +Pased as delegate in xmlParser constructor and called as callback by +xmlParser:parse(xml) method. + +\section{History} + +This library is fork of LuaXML library originaly created by Paul +Chakravarti. Its original version can be found at +\url{http://manoelcampos.com/files/LuaXML--0.0.0-lua5.1.tgz}. Some files not +needed for use with luatex were droped from the distribution. +Documentation was converted from original comments in the source code. + +\section{License} + +This code is freely distributable under the terms of the Lua license +(\url{http://www.lua.org/copyright.html}) +\end{document} diff --git a/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-handler.lua b/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-handler.lua new file mode 100644 index 00000000000..bc4d8ea9120 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-handler.lua @@ -0,0 +1,338 @@ +module(...,package.seeall) +-- +-- Overview: +-- ========= +-- Standard XML event handler(s) for XML parser module (xml.lua) +-- +-- Features: +-- ========= +-- printHandler - Generate XML event trace +-- domHandler - Generate DOM-like node tree +-- simpleTreeHandler - Generate 'simple' node tree +-- simpleTeXhandler - SAX like handler with support for CSS selectros +-- +-- API: +-- ==== +-- Must be called as handler function from xmlParser +-- and implement XML event callbacks (see xmlParser.lua +-- for callback API definition) +-- +-- printHandler: +-- ------------- +-- +-- printHandler prints event trace for debugging +-- +-- domHandler: +-- ----------- +-- +-- domHandler generates a DOM-like node tree structure with +-- a single ROOT node parent - each node is a table comprising +-- fields below. +-- +-- node = { _name = , +-- _type = ROOT|ELEMENT|TEXT|COMMENT|PI|DECL|DTD, +-- _attr = { Node attributes - see callback API }, +-- _parent = +-- _children = { List of child nodes - ROOT/NODE only } +-- } +-- +-- The dom structure is capable of representing any valid XML document +-- +-- simpleTreeHandler +-- ----------------- +-- +-- simpleTreeHandler is a simplified handler which attempts +-- to generate a more 'natural' table based structure which +-- supports many common XML formats. +-- +-- The XML tree structure is mapped directly into a recursive +-- table structure with node names as keys and child elements +-- as either a table of values or directly as a string value +-- for text. Where there is only a single child element this +-- is inserted as a named key - if there are multiple +-- elements these are inserted as a vector (in some cases it +-- may be preferable to always insert elements as a vector +-- which can be specified on a per element basis in the +-- options). Attributes are inserted as a child element with +-- a key of '_attr'. +-- +-- Only Tag/Text & CDATA elements are processed - all others +-- are ignored. +-- +-- This format has some limitations - primarily +-- +-- * Mixed-Content behaves unpredictably - the relationship +-- between text elements and embedded tags is lost and +-- multiple levels of mixed content does not work +-- * If a leaf element has both a text element and attributes +-- then the text must be accessed through a vector (to +-- provide a container for the attribute) +-- +-- In general however this format is relatively useful. +-- +-- It is much easier to understand by running some test +-- data through 'textxml.lua -simpletree' than to read this) +-- +-- Options +-- ======= +-- simpleTreeHandler.options.noReduce = { = bool,.. } +-- +-- - Nodes not to reduce children vector even if only +-- one child +-- +-- domHandler.options.(comment|pi|dtd|decl)Node = bool +-- +-- - Include/exclude given node types +-- +-- Usage +-- ===== +-- Pased as delegate in xmlParser constructor and called +-- as callback by xmlParser:parse(xml) method. +-- +-- See textxml.lua for examples +-- License: +-- ======== +-- +-- This code is freely distributable under the terms of the Lua license +-- (http://www.lua.org/copyright.html) +-- +-- History +-- ======= +-- $Id: handler.lua,v 1.1.1.1 2001/11/28 06:11:33 paulc Exp $ +-- +-- $Log: handler.lua,v $ +-- Revision 1.1.1.1 2001/11/28 06:11:33 paulc +-- Initial Import +--@author Paul Chakravarti (paulc@passtheaardvark.com)

+ + +---Handler to generate a string prepresentation of a table +--Convenience function for printHandler (Does not support recursive tables). +--@param t Table to be parsed +--@returns Returns a string representation of table + +local stack = require("luaxml-stack") + +function showTable(t) + local sep = '' + local res = '' + if type(t) ~= 'table' then + return t + end + for k,v in pairs(t) do + if type(v) == 'table' then + v = showTable(v) + end + res = res .. sep .. string.format("%s=%s",k,v) + sep = ',' + end + res = '{'..res..'}' + return res +end + +---Handler to generate a simple event trace +printHandler = function() + local obj = {} + obj.starttag = function(self,t,a,s,e) + io.write("Start : "..t.."\n") + if a then + for k,v in pairs(a) do + io.write(string.format(" + %s='%s'\n",k,v)) + end + end + end + obj.endtag = function(self,t,s,e) + io.write("End : "..t.."\n") + end + obj.text = function(self,t,s,e) + io.write("Text : "..t.."\n") + end + obj.cdata = function(self,t,s,e) + io.write("CDATA : "..t.."\n") + end + obj.comment = function(self,t,s,e) + io.write("Comment : "..t.."\n") + end + obj.dtd = function(self,t,a,s,e) + io.write("DTD : "..t.."\n") + if a then + for k,v in pairs(a) do + io.write(string.format(" + %s='%s'\n",k,v)) + end + end + end + obj.pi = function(self,t,a,s,e) + io.write("PI : "..t.."\n") + if a then + for k,v in pairs(a) do + io. write(string.format(" + %s='%s'\n",k,v)) + end + end + end + obj.decl = function(self,t,a,s,e) + io.write("XML Decl : "..t.."\n") + if a then + for k,v in pairs(a) do + io.write(string.format(" + %s='%s'\n",k,v)) + end + end + end + return obj +end + +---Handler to generate a lua table from a XML content string +function simpleTreeHandler() + local obj = {} + + obj.root = {} + obj.stack = {obj.root;n=1} + obj.options = {noreduce = {}} + + obj.reduce = function(self,node,key,parent) + -- Recursively remove redundant vectors for nodes + -- with single child elements + for k,v in pairs(node) do + if type(v) == 'table' then + self:reduce(v,k,node) + end + end + if table.getn(node) == 1 and not self.options.noreduce[key] and + node._attr == nil then + parent[key] = node[1] + else + node.n = nil + end + end + + obj.starttag = function(self,t,a) + local node = {} + if self.parseAttributes == true then + node._attr=a + end + + local current = self.stack[table.getn(self.stack)] + if current[t] then + table.insert(current[t],node) + else + current[t] = {node;n=1} + end + table.insert(self.stack,node) + end + + obj.endtag = function(self,t,s) + local current = self.stack[table.getn(self.stack)] + local prev = self.stack[table.getn(self.stack)-1] + if not prev[t] then + error("XML Error - Unmatched Tag ["..s..":"..t.."]\n") + end + if prev == self.root then + -- Once parsing complete recursively reduce tree + self:reduce(prev,nil,nil) + end + table.remove(self.stack) + end + + obj.text = function(self,t) + local current = self.stack[table.getn(self.stack)] + table.insert(current,t) + end + + obj.cdata = obj.text + + return obj +end + + + +--- domHandler +function domHandler() + local obj = {} + obj.options = {commentNode=1,piNode=1,dtdNode=1,declNode=1} + obj.root = { _children = {n=0}, _type = "ROOT" } + obj.current = obj.root + obj.starttag = function(self,t,a) + local node = { _type = 'ELEMENT', + _name = t, + _attr = a, + _parent = self.current, + _children = {n=0} } + table.insert(self.current._children,node) + self.current = node + end + obj.endtag = function(self,t,s) + if t ~= self.current._name then + error("XML Error - Unmatched Tag ["..s..":"..t.."]\n") + end + self.current = self.current._parent + end + obj.text = function(self,t) + local node = { _type = "TEXT", + _parent = self.current, + _text = t } + table.insert(self.current._children,node) + end + obj.comment = function(self,t) + if self.options.commentNode then + local node = { _type = "COMMENT", + _parent = self.current, + _text = t } + table.insert(self.current._children,node) + end + end + obj.pi = function(self,t,a) + if self.options.piNode then + local node = { _type = "PI", + _name = t, + _attr = a, + _parent = self.current } + table.insert(self.current._children,node) + end + end + obj.decl = function(self,t,a) + if self.options.declNode then + local node = { _type = "DECL", + _name = t, + _attr = a, + _parent = self.current } + table.insert(self.current._children,node) + end + end + obj.dtd = function(self,t,a) + if self.options.dtdNode then + local node = { _type = "DTD", + _name = t, + _attr = a, + _parent = self.current } + table.insert(self.current._children,node) + end + end + obj.cdata = obj.text + return obj +end + +-- +simpleTeXhandler=function() + local obj={} + local _stack=stack.Stack:Create() + obj.starttag = function(self,t,a,s,e) + local tag = {t} + local getAtt = function(att) + if a[att] then + return att.."="..a[att] + end + return nil + end + if type(a) == "table" then + table.insert(tag,getAtt("id")) + table.insert(tag,getAtt("class")) + end + _stack:push("<"..table.concat(tag," ")..">") + io.write(_stack:join("").."\n") +-- io.write("Start "..t.."\n" ) + end + obj.endtag = function(self,t,s,e) + _stack:pop() + -- io.write("End : "..t.."\n") + end + return obj +end diff --git a/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-xml.lua b/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-xml.lua new file mode 100644 index 00000000000..f3ebb0445e8 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaxml/luaxml-mod-xml.lua @@ -0,0 +1,547 @@ +module(...,package.seeall) +--- +-- Overview: +-- ========= +-- +-- This module provides a non-validating XML stream parser in Lua. +-- +-- Features: +-- ========= +-- +-- * Tokenises well-formed XML (relatively robustly) +-- * Flexible handler based event api (see below) +-- * Parses all XML Infoset elements - ie. +-- - Tags +-- - Text +-- - Comments +-- - CDATA +-- - XML Decl +-- - Processing Instructions +-- - DOCTYPE declarations +-- * Provides limited well-formedness checking +-- (checks for basic syntax & balanced tags only) +-- * Flexible whitespace handling (selectable) +-- * Entity Handling (selectable) +-- +-- Limitations: +-- ============ +-- +-- * Non-validating +-- * No charset handling +-- * No namespace support +-- * Shallow well-formedness checking only (fails +-- to detect most semantic errors) +-- +-- API: +-- ==== +-- +-- The parser provides a partially object-oriented API with +-- functionality split into tokeniser and hanlder components. +-- +-- The handler instance is passed to the tokeniser and receives +-- callbacks for each XML element processed (if a suitable handler +-- function is defined). The API is conceptually similar to the +-- SAX API but implemented differently. +-- +-- The following events are generated by the tokeniser +-- +-- handler:start - Start Tag +-- handler:end - End Tag +-- handler:text - Text +-- handler:decl - XML Declaration +-- handler:pi - Processing Instruction +-- handler:comment - Comment +-- handler:dtd - DOCTYPE definition +-- handler:cdata - CDATA +-- +-- The function prototype for all the callback functions is +-- +-- callback(val,attrs,start,end) +-- +-- where attrs is a table and val/attrs are overloaded for +-- specific callbacks - ie. +-- +-- Callback val attrs (table) +-- -------- --- ------------- +-- start name { attributes (name=val).. } +-- end name nil +-- text nil +-- cdata nil +-- decl "xml" { attributes (name=val).. } +-- pi pi name { attributes (if present).. +-- _text = +-- } +-- comment nil +-- dtd root element { _root = , +-- _type = SYSTEM|PUBLIC, +-- _name = , +-- _uri = , +-- _internal = +-- } +-- +-- (start & end provide the character positions of the start/end +-- of the element) +-- +-- XML data is passed to the parser instance through the 'parse' +-- method (Nore: must be passed a single string currently) +-- +-- Options +-- ======= +-- +-- Parser options are controlled through the 'self.options' table. +-- Available options are - +-- +-- * stripWS +-- +-- Strip non-significant whitespace (leading/trailing) +-- and do not generate events for empty text elements +-- +-- * expandEntities +-- +-- Expand entities (standard entities + single char +-- numeric entities only currently - could be extended +-- at runtime if suitable DTD parser added elements +-- to table (see obj._ENTITIES). May also be possible +-- to expand multibyre entities for UTF-8 only +-- +-- * errorHandler +-- +-- Custom error handler function +-- +-- NOTE: Boolean options must be set to 'nil' not '0' +-- +-- Usage +-- ===== +-- +-- Create a handler instance - +-- +-- h = { start = function(t,a,s,e) .... end, +-- end = function(t,a,s,e) .... end, +-- text = function(t,a,s,e) .... end, +-- cdata = text } +-- +-- (or use predefined handler - see handler.lua) +-- +-- Create parser instance - +-- +-- p = xmlParser(h) +-- +-- Set options - +-- +-- p.options.xxxx = nil +-- +-- Parse XML data - +-- +-- xmlParser:parse(" + +local format= string.format +---Parses a XML string +--@param handler Handler object to be used to convert the XML string +--to another formats. @see handler.lua +xmlParser = function(handler) + local obj = {} + -- Public attributes + + obj.options = { + stripWS = 1, + expandEntities = 1, + errorHandler = function(err,pos) + error(format("%s [char=%d]\n", + err or "Parse Error",pos)) + end, + } + + -- Public methods + + obj.parse = function(self, str, parseAttributes) + if parseAttributes == nil then + parseAttributes = true + end + self._handler.parseAttributes = parseAttributes + + local match,endmatch,pos = 0,0,1 + local text,endt1,endt2,tagstr,tagname,attrs,starttext,endtext + local errstart,errend,extstart,extend + while match do + -- Get next tag (first pass - fix exceptions below) + match,endmatch,text,endt1,tagstr,endt2 = string.find(str,self._XML,pos) + if not match then + if string.find(str,self._WS,pos) then + -- No more text - check document complete + if table.getn(self._stack) ~= 0 then + self:_err(self._errstr.incompleteXmlErr,pos) + else + break + end + else + -- Unparsable text + self:_err(self._errstr.xmlErr,pos) + end + end + -- Handle leading text + starttext = match + endtext = match + string.len(text) - 1 + match = match + string.len(text) + text = self:_parseEntities(self:_stripWS(text)) + if text ~= "" and self._handler.text then + self._handler:text(text,nil,match,endtext) + end + -- Test for tag type + if string.find(string.sub(tagstr,1,5),"?xml%s") then + -- XML Declaration + match,endmatch,text = string.find(str,self._PI,pos) + if not match then + self:_err(self._errstr.declErr,pos) + end + if match ~= 1 then + -- Must be at start of doc if present + self:_err(self._errstr.declStartErr,pos) + end + tagname,attrs = self:_parseTag(text) + -- TODO: Check attributes are valid + -- Check for version (mandatory) + if attrs.version == nil then + self:_err(self._errstr.declAttrErr,pos) + end + if self._handler.decl then + self._handler:decl(tagname,attrs,match,endmatch) + end + elseif string.sub(tagstr,1,1) == "?" then + -- Processing Instruction + match,endmatch,text = string.find(str,self._PI,pos) + if not match then + self:_err(self._errstr.piErr,pos) + end + if self._handler.pi then + -- Parse PI attributes & text + tagname,attrs = self:_parseTag(text) + local pi = string.sub(text,string.len(tagname)+1) + if pi ~= "" then + if attrs then + attrs._text = pi + else + attrs = { _text = pi } + end + end + self._handler:pi(tagname,attrs,match,endmatch) + end + elseif string.sub(tagstr,1,3) == "!--" then + -- Comment + match,endmatch,text = string.find(str,self._COMMENT,pos) + if not match then + self:_err(self._errstr.commentErr,pos) + end + if self._handler.comment then + text = self:_parseEntities(self:_stripWS(text)) + self._handler:comment(text,next,match,endmatch) + end + elseif string.sub(tagstr,1,8) == "!DOCTYPE" then + -- DTD + --match,endmatch,attrs = self:_parseDTD(string,pos) + match,endmatch,attrs = self:_parseDTD(str,pos) + if not match then + self:_err(self._errstr.dtdErr,pos) + end + if self._handler.dtd then + self._handler:dtd(attrs._root,attrs,match,endmatch) + end + elseif string.sub(tagstr,1,8) == "![CDATA[" then + -- CDATA + match,endmatch,text = string.find(str,self._CDATA,pos) + if not match then + self:_err(self._errstr.cdataErr,pos) + end + if self._handler.cdata then + self._handler:cdata(text,nil,match,endmatch) + end + else + -- Normal tag + + -- Need theck for embedded '>' in attribute value and extend + -- match recursively if necessary eg. + + while 1 do + errstart,errend = string.find(tagstr,self._ATTRERR1) + if errend == nil then + errstart,errend = string.find(tagstr,self._ATTRERR2) + if errend == nil then + break + end + end + extstart,extend,endt2 = string.find(str,self._TAGEXT,endmatch+1) + tagstr = tagstr .. string.sub(string,endmatch,extend-1) + if not match then + self:_err(self._errstr.xmlErr,pos) + end + endmatch = extend + end + + -- Extract tagname/attrs + + tagname,attrs = self:_parseTag(tagstr) + + if (endt1=="/") then + -- End tag + if self._handler.endtag then + if attrs then + -- Shouldnt have any attributes in endtag + self:_err(format("%s (/%s)", + self._errstr.endTagErr, + tagname) + ,pos) + end + if table.remove(self._stack) ~= tagname then + self:_err(format("%s (/%s)", + self._errstr.unmatchedTagErr, + tagname) + ,pos) + end + self._handler:endtag(tagname,nil,match,endmatch) + end + else + -- Start Tag + table.insert(self._stack,tagname) + if self._handler.starttag then + self._handler:starttag(tagname,attrs,match,endmatch) + end + -- Self-Closing Tag + if (endt2=="/") then + table.remove(self._stack) + if self._handler.endtag then + self._handler:endtag(tagname,nil,match,endmatch) + end + end + end + end + pos = endmatch + 1 + end + end + + -- Private attrobures/functions + + obj._handler = handler + obj._stack = {} + + obj._XML = '^([^<]*)<(%/?)([^>]-)(%/?)>' + obj._ATTR1 = '([%w-:_]+)%s*=%s*"(.-)"' + obj._ATTR2 = '([%w-:_]+)%s*=%s*\'(.-)\'' + obj._CDATA = '<%!%[CDATA%[(.-)%]%]>' + obj._PI = '<%?(.-)%?>' + obj._COMMENT = '' + obj._TAG = '^(.-)%s.*' + obj._LEADINGWS = '^%s+' + obj._TRAILINGWS = '%s+$' + obj._WS = '^%s*$' + obj._DTD1 = '' + obj._DTD2 = '' + obj._DTD3 = '' + obj._DTD4 = '' + obj._DTD5 = '' + --obj._DTD6 = "" + + obj._ATTRERR1 = '=%s*"[^"]*$' + obj._ATTRERR2 = '=%s*\'[^\']*$' + obj._TAGEXT = '(%/?)>' + + obj._ENTITIES = { ["<"] = "<", + [">"] = ">", + ["&"] = "&", + ["""] = '"', + ["'"] = "'", + ["&#(%d+);"] = function (x) + local d = tonumber(x) + if d >= 0 and d < 256 then + return string.char(d) + else + return "&#"..d..";" + end + end, + ["&#x(%x+);"] = function (x) + local d = tonumber(x,16) + if d >= 0 and d < 256 then + return string.char(d) + else + return "&#x"..x..";" + end + end, + } + + obj._err = function(self,err,pos) + if self.options.errorHandler then + self.options.errorHandler(err,pos) + end + end + + obj._errstr = { xmlErr = "Error Parsing XML", + declErr = "Error Parsing XMLDecl", + declStartErr = "XMLDecl not at start of document", + declAttrErr = "Invalid XMLDecl attributes", + piErr = "Error Parsing Processing Instruction", + commentErr = "Error Parsing Comment", + cdataErr = "Error Parsing CDATA", + dtdErr = "Error Parsing DTD", + endTagErr = "End Tag Attributes Invalid", + unmatchedTagErr = "Unbalanced Tag", + incompleteXmlErr = "Incomplete XML Document", + } + + obj._stripWS = function(self,s) + if self.options.stripWS then + s = string.gsub(s,'^%s+','') + s = string.gsub(s,'%s+$','') + end + return s + end + + obj._parseEntities = function(self,s) + if self.options.expandEntities then + --for k,v in self._ENTITIES do + for k,v in pairs(self._ENTITIES) do + --print (k, v) + s = string.gsub(s,k,v) + end + end + return s + end + + obj._parseDTD = function(self,s,pos) + -- match,endmatch,root,type,name,uri,internal + --print(s.." : "..pos) + local m,e,r,t,n,u,i + m,e,r,t,n,u = string.find(s,self._DTD5,pos) + if m then + return m,e,{_root=r,_type=t,_name=n,_uri=u} + end + m,e,r,t,u,i = string.find(s,self._DTD1,pos) + if m then + return m,e,{_root=r,_type=t,_uri=u,_internal=i} + end + m,e,r,t,n,u,i = string.find(s,self._DTD2,pos) + if m then + return m,e,{_root=r,_type=t,_name=n,_uri=u,_internal=i} + end + m,e,r,i = string.find(s,self._DTD3,pos) + if m then + return m,e,{_root=r,_internal=i} + end + m,e,r,t,u = string.find(s,self._DTD4,pos) + if m then + return m,e,{_root=r,_type=t,_uri=u} + end + return nil + end + + obj._parseTag = function(self,s) + local attrs = {} + local tagname = string.gsub(s,self._TAG,'%1') + string.gsub(s,self._ATTR1,function (k,v) + attrs[string.lower(k)]=self:_parseEntities(v) + attrs._ = 1 + end) + string.gsub(s,self._ATTR2,function (k,v) + attrs[string.lower(k)]=self:_parseEntities(v) + attrs._ = 1 + end) + if attrs._ then + attrs._ = nil + else + attrs = nil + end + return tagname,attrs + end + + return obj + +end + +function xmlEscape(s) + local t = {['"']=""",["'"]="'",["&"]="&",["<"]="<",[">"]=">"} + return string.gsub(s,"([\"'<>&])",t) +end + + + +function serialize(tb) +local function getAttributes(k,v) + local i = "" + if(type(v["_attr"])=="table") then + -- texio.write_nl("attr") + for p,n in pairs(v["_attr"]) do + i = i ..' '.. p .. '="'..xmlEscape(n)..'"' + end + --table.remove(v,"_attr") + end + return i +end + local function printable(tb, level,currTag) + local r ={} + local currTag = currTag or "" + level = level or 0 + local spaces = string.rep(' ', level*2) + for k,v in pairs(tb) do + if type(v) ~= "table" then + local ct = k + if type(k)=="number" then + ct = currTag + end + if ct == "" then + table.insert(r,spaces .. xmlEscape(v).."\n") + else + local i = getAttributes(k,v) + table.insert(r,spaces .. '<'..ct..i..'>'..xmlEscape(v)..''.."\n") + end + else + if k == "_attr" then + --table.insert(r,printable(v, level)) + else + if type(k)=="string" then + --currTag = k + if type(k)=="numeric" then + k = currTag + end + if #v > 1 then + table.insert(r,printable(v, level+1,k)) + else + local i = getAttributes(k,v) + table.insert(r,spaces.."<"..k..i..">\n") + table.insert(r,printable(v, level+1,k)) + table.insert(r,spaces.."\n") + end + else + local i = getAttributes(k,v) + table.insert(r,spaces .. "<"..currTag..i..">\n") + --level = level + 1 + table.insert(r,printable(v, level+1)) + table.insert(r,spaces .. "\n") + end + end + end + end + return table.concat(r,"") + end + return table.concat({'',printable(tb)},"\n") +end diff --git a/Master/texmf-dist/tex/luatex/luaxml/luaxml-selectors.lua b/Master/texmf-dist/tex/luatex/luaxml/luaxml-selectors.lua new file mode 100644 index 00000000000..921f971eb2e --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaxml/luaxml-selectors.lua @@ -0,0 +1,42 @@ +module(...,package.seeall) + + +function makeTag(s) + return "<"..s.."[^>]*>" +end +function matchTag(tg) + return makeTag(tg) +end + +function matchDescendand(a,b) + return makeTag(a)..makeTag(b) +end + +function matchChild(a,b) + return makeTag(a)..".*"..makeTag(b) +end + +function matchSibling(a,b) + return makeTag(a .. "[^>]*".."@%("..b.."[^>]*%)") +end + +function matchClass(tg,class) + return makeTag(tg.."[^>]*class=[|]*[^>]*|"..class.."[^>]*|") +end +matcher = {} +function matcher.new() + local self = {} + local selectors={} + function self:addSelector(sel,val) + selectors[sel.."$"] = val + end + function self:testPath(path,fn) + for k, v in pairs(selectors) do + if path:match(k) then + fn(v) + end + end + end + return self +end + diff --git a/Master/texmf-dist/tex/luatex/luaxml/luaxml-stack.lua b/Master/texmf-dist/tex/luatex/luaxml/luaxml-stack.lua new file mode 100644 index 00000000000..54386ff84d3 --- /dev/null +++ b/Master/texmf-dist/tex/luatex/luaxml/luaxml-stack.lua @@ -0,0 +1,63 @@ +-- Code from http://lua-users.org/wiki/SimpleStack +module(...,package.seeall) +Stack = {} + +-- Create a Table with stack functions +function Stack:Create() + + -- stack table + local t = {} + -- entry table + t._et = {} + + -- push a value on to the stack + function t:push(...) + if ... then + local targs = {...} + -- add values + for _,v in pairs(targs) do + table.insert(self._et, v) + end + end + end + + -- pop a value from the stack + function t:pop(num) + + -- get num values from stack + local num = num or 1 + + -- return table + local entries = {} + + -- get values into entries + for i = 1, num do + -- get last entry + if #self._et ~= 0 then + table.insert(entries, self._et[#self._et]) + -- remove last value + table.remove(self._et) + else + break + end + end + -- return unpacked entries + return unpack(entries) + end + + -- get entries + function t:getn() + return #self._et + end + + -- list values + function t:list() + for i,v in pairs(self._et) do + print(i, v) + end + end + function t:join(s) + return table.concat(self._et,s) + end + return t +end diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 54e6a93a55e..0d5de27a9d0 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -252,7 +252,7 @@ my @TLP_working = qw( lua-alt-getopt lua-check-hyphen lua-visual-debug lua2dox luabibentry luacode luaindex luainputenc lualatex-doc lualatex-math lualibs luamplib luaotfload - luapersian luasseq luatexbase luatexja luatextra + luapersian luasseq luatexbase luatexja luatextra luaxml lxfonts ly1 macqassign macros2e mafr magaz magyar mailing mailmerge makebarcode makebox makecell makecirc makecmds makedtx makeglos makeplot diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index 13198c3d96a..f3f8fa3309c 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -1320,6 +1320,7 @@ $standardtex='\.(.bx|cfg|sty|clo|ldf|cls|def|fd|cmap|4ht)$'; 'lua-visual-debug', '\.lua|' . $standardtex, 'lua2dox', 'NULL', # .def is lua code 'lualatex-math', '\.sty', # not phst-doc.cls + 'luaxml', '\.lua|' . $standardtex, 'magyar', 'NULL', # do not install in runtime, conflicts with babel 'manjutex', '\.sty|\.clo|\.ldf|\.cls|\.def|\.fd$|manju.tex', 'math-e', 'NULL', diff --git a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc index 5713f8fd6bf..63412456e54 100644 --- a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc @@ -24,4 +24,5 @@ depend luapersian depend luasseq depend luatexbase depend luatextra +depend luaxml depend showhyphens diff --git a/Master/tlpkg/tlpsrc/luaxml.tlpsrc b/Master/tlpkg/tlpsrc/luaxml.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3