
| Lesson
1 Lesson 2 Lesson 3 Lesson 4 Lesson 5 Lesson 6 Lesson 7 Lesson 8 Lesson 9 Lesson 10 Lesson 11 Lesson 12 Lesson 13 Lesson 14 Lesson 15 Lesson 16 Lesson 17 Lesson 18 Lesson 19 |
Lesson 11 Parsing XMLIn addition to using the parse() function of zeArray to transfer data between a text string to numbers, you can use the zeExpat object, a very primitive binding of Lua with the EXPAT library, to parse XML string or to save data to and load data from a XML file. zeGraph also has zeHDF, zeNetCDF, and zeBIO objects for binary data serialization. You can also use zeSqlite to manage a relational datase. Using zeExpat is no more difficult than understanding the callback mechanism. To explains the mechanism, let's create a XML file first:
require("register")
arr = zeUtl.new("int")
arr:range(1, 1, 9)
arr:reshape(3, 3)
file = io.open("array.txt", "a") -- io is Lua's building function
file:write("array type = \"int\" nrec = \"3\" nvec = \"3\"\n")
file:write(" commentTest XML input/output/comment\n")
file:write(" data\n")
file:flush()
arr:print(" ", " ", "array.txt")
file:write(" /data\n")
file:write("/array\n")
file:flush()
--[[Outputs in array.text file:
array type = "int" nrec = "3" nvec = "3"
commentTest XML input/output/comment
data
1 4 7
2 5 8
3 6 9
/data
/array
]]
Note that the file should be opened for appending so that the Lua IO functions properly append outputs after the array prints its contents to the file. Now let's just implement the start-tag callback, end-tag callback, and data callback functions to examine the feedback contents from zeExpat:
require("register")
--The start, end, and data callback functions print whatever comes from the parser.
f1 = function(n, s, t) -- start-tag callback
print("f1", n, s)
if (t) then
for k, v in t do print("f1", k, v) end
end
end
f2 = function(n, s) -- end-tag callback
print("f2", n, s)
end
f3 = function(n, s, l) -- data callback
print("f3", n, s, l)
end
-- Create a zeExpat object
xml = zeUtl.new("xml", "f1", "f2", "f3");
for line in io.lines("array.txt") do
xml:parse(line)
end
--[[Outputs:
f1 1 array
f1 nvec 3
f1 type int
f1 nrec 3
f3 1 2
f1 2 comment
f3 2 Test XML input/output 21
f2 2 comment
f3 1 2
f1 2 data
f3 2 1 4 7 7
f3 2 2 5 8 7
f3 2 3 6 9 7
f3 2 2
f2 2 data
f2 1 array
]]
If you understand the parsing process described so far and notice that blanks before a tag are treated as data content, recovering data from a file becomes trivial, as shown below:
require("register")
ivec = 0
info = {} --save tags and array info in this table
f1 = function(n, s, t)
info[s] = 1
if (t) then
for k, v in t do info[k] = v; end
end
if (s == "array") then
arr = zeUtl.new("int")
arr:resize(tonumber(info.nrec), tonumber(info.nvec))
end
end
f2 = function(n, s)
info[s] = 0
end
f3 = function(n, s, l)
--You should implement a better method to escape blank string
if (info.data and l > 2) then
arr:parse(ivec, s)
ivec = ivec + 1
end
end
xml = zeUtl.new("xml", "f1", "f2", "f3");
for line in io.lines("array.txt") do
xml:parse(line)
end
arr:print()
--[[Outputs:
1, 4, 7
2, 5, 8
3, 6, 9
]]
|