1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
-- * Lua module for writing simple XML * --
-- * Class for writing XML * --
XmlOutput = {}
-- class constructor
function XmlOutput:Create()
obj = {
Out = {}, IndentStep = 2, Indent = 0,
ElStack = {len = 0},
ExpectEOL = false, PreserveSpace = false,
EOL_Str = "\n"}
obj.ElStack.Peek = function(self)
return self[self.len]
end
obj.ElStack.Push = function(self, Value)
local len = self.len + 1
self.len = len
self[len] = Value
end
obj.ElStack.Pop = function(self)
local len = self.len
if len == 0 then error("Element stack is empty") end
local value = self[len]
self[len] = nil -- to allow garbage collection
self.len = len - 1
return value
end
setmetatable(obj, {__index = self})
return obj
end
-- write to output stream
function XmlOutput:GetText()
return table.concat(self.Out)
end
-- write to output stream
function XmlOutput:Write(Data)
if Data == "" then return end
table.insert(self.Out, Data)
end
-- a function used internally
function XmlOutput:DataAdded()
if self.ElStack.len ~= 0 then
if self.ElStack:Peek().Empty then
self:Write('>')
self.ExpectEOL = true
end
self.ElStack:Peek().Empty = False
end
if self.ExpectEOL then
if not self.PreserveSpace then self:Write(self.EOL_Str) end
self.ExpectEOL = false
end
end
-- open XML tag
function XmlOutput:OpenTag(Tag)
self:DataAdded()
Data = {Tag = Tag, Empty = true}
self.ElStack:Push(Data)
if not self.PreserveSpace then
self:Write(string.rep(" ", self.Indent))
end
self:Write("<")
self:Write(Tag)
self.Indent = self.Indent + self.IndentStep
end
-- add attribute to current opening tag
function XmlOutput:AddAttribute(Name, Value)
self:Write(string.format(' %s="%s"', Name, Value))
end
-- add a list of attributes to current opening tag
function XmlOutput:AddAttributes(Attr)
if Attr then
for k,v in pairs(Attr) do
self:Write(string.format(' %s="%s"', k, v))
end
end
end
-- add text inside current tag
function XmlOutput:AddText(Data)
self:DataAdded()
self:Write(Data)
end
-- close XML tag
function XmlOutput:CloseTag()
local Data = self.ElStack:Pop()
self.Indent = self.Indent - self.IndentStep
if Data.Empty then
self:Write("/>")
else
self:DataAdded()
if not self.PreserveSpace then
self:Write(string.rep(" ", self.Indent))
end
self:Write(string.format("</%s>", Data.Tag))
end
self.ExpectEOL = true
end
-- add comment to XML
function XmlOutput:AddComment(Data)
self:DataAdded()
self:Write(string.format("<!--%s-->", Data))
self.ExpectEOL = true
end
|