cocos2d lua集成XML教程

Installation
  1. Copy the xmlSimple.lua file to your project.
  2. Create a local variable local xml = require("xmlSimple.lua").newParser()
  3. Read xml using xml:ParseXmlText(xmlString) or xml:loadFile(xmlFilename, base)

Parsing XML

 one="two">
     four="five" four="six"/>
    eight
     ten="eleven">twelve

You can access values in two ways:

Using the simple method:

xml.test["@one"] == "two"
xml.test.nine["@ten"] == "eleven"
xml.test.nine:value() == "twelve"
xml.test.three[1]["@four"][1] == "five"
xml.test.three[1]["@four"][2] == "six"
xml.test.three[2]:value() == "eight"

or if your XML is a little bit more complicated you can do it like this:

xml:children()[1]:name() == "test"
xml:children()[1]:children()[2]:value() == "eight"
xml:properties()[1] == {name = "one", value = "two"}

Limitations

There's no support for namespaces. When I see namespaces I immediately start to remember days when I worked at corporate. We had to use namespaces only because XML was so convoluted we would not be able to handle it without them. In the end XML parsing took longer for some APIs then actual logic of the API. If you're in this situation it is better to step back and do something about it rather than asking for namespace support. I am using this module to read fairly simple XML. Even if it is a large XML string, the structure is still simple, so I was not able to test it properly. Please create a new Issue if you spot a problem. Please take a loook at xmlTest.lua for an example of use.

Final notes

This is a modified version of Corona-XML-Module by Jonathan Beebe which in turn is based on Alexander Makeev's Lua-only XML parser found here


xmlSimple.lua 的代码

module(..., package.seeall)

---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
--
-- xml.lua - XML parser for use with the Corona SDK.
--
-- version: 1.2
--
-- CHANGELOG:
--
-- 1.2 - Created new structure for returned table
-- 1.1 - Fixed base directory issue with the loadFile() function.
--
-- NOTE: This is a modified version of Alexander Makeev's Lua-only XML parser
-- found here: http://lua-users.org/wiki/LuaXml
--
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
function newParser()

    XmlParser = {};

    function XmlParser:ToXmlString(value)
        value = string.gsub(value, "&", "&"); -- '&' -> "&"
        value = string.gsub(value, "<", "<"); -- '<' -> "<"
        value = string.gsub(value, ">", ">"); -- '>' -> ">"
        value = string.gsub(value, "\"", """); -- '"' -> """
        value = string.gsub(value, "([^%w%&%;%p%\t% ])",
            function(c)
                return string.format("&#x%X;", string.byte(c))
            end);
        return value;
    end

    function XmlParser:FromXmlString(value)
        value = string.gsub(value, "&#x([%x]+)%;",
            function(h)
                return string.char(tonumber(h, 16))
            end);
        value = string.gsub(value, "&#([0-9]+)%;",
            function(h)
                return string.char(tonumber(h, 10))
            end);
        value = string.gsub(value, """, "\"");
        value = string.gsub(value, "'", "'");
        value = string.gsub(value, ">", ">");
        value = string.gsub(value, "<", "<");
        value = string.gsub(value, "&", "&");
        return value;
    end

    function XmlParser:ParseArgs(node, s)
        string.gsub(s, "([%w_]+)%s*=%s*([\"'])(.-)%2", function(w, _, a)
            node:addProperty(w, self:FromXmlString(a))
        end)
    end

    function XmlParser:ParseXmlText(xmlText)
        local stack = {}
        local top = newNode()
        table.insert(stack, top)
        local ni, c, label, xarg, empty
        local i, j = 1, 1
        while true do
            ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
            if not ni then break end
            local text = string.sub(xmlText, i, ni - 1);
            if not string.find(text, "^%s*$") then
                local lVal = (top:value() or "") .. self:FromXmlString(text)
                stack[#stack]:setValue(lVal)
            end
            if empty == "/" then -- empty element tag
                local lNode = newNode(label)
                self:ParseArgs(lNode, xarg)
                top:addChild(lNode)
            elseif c == "" then -- start tag
                local lNode = newNode(label)
                self:ParseArgs(lNode, xarg)
                table.insert(stack, lNode)
		top = lNode
            else -- end tag
                local toclose = table.remove(stack) -- remove top

                top = stack[#stack]
                if #stack < 1 then
                    error("XmlParser: nothing to close with " .. label)
                end
                if toclose:name() ~= label then
                    error("XmlParser: trying to close " .. toclose.name .. " with " .. label)
                end
                top:addChild(toclose)
            end
            i = j + 1
        end
        local text = string.sub(xmlText, i);
        if #stack > 1 then
            error("XmlParser: unclosed " .. stack[#stack]:name())
        end
        return top
    end



    function XmlParser:loadFile(xmlFilename, base)
	if not xmlFilename then
		return nil;
	end 
	
	base = base or "";
        path = base .. xmlFilename;
	
        local hFile, err = io.open(path, "r");

        if hFile and not err then
            local xmlText = hFile:read("*all"); -- read file content
            io.close(hFile);
            return self:ParseXmlText(xmlText), nil;
        else
            print(err)
            return nil
        end
    end

    return XmlParser
end

function newNode(name)
    local node = {}
    node.___value = nil
    node.___name = name
    node.___children = {}
    node.___props = {}

    function node:value() return self.___value end
    function node:setValue(val) self.___value = val end
    function node:name() return self.___name end
    function node:setName(name) self.___name = name end
    function node:children() return self.___children end
    function node:numChildren() return #self.___children end
    function node:addChild(child)
        if self[child:name()] ~= nil then
            if type(self[child:name()].name) == "function" then
                local tempTable = {}
                table.insert(tempTable, self[child:name()])
                self[child:name()] = tempTable
            end
            table.insert(self[child:name()], child)
        else
            self[child:name()] = child
        end
        table.insert(self.___children, child)
    end

    function node:properties() return self.___props end
    function node:numProperties() return #self.___props end
    function node:addProperty(name, value)
        local lName = "@" .. name
        if self[lName] ~= nil then
            if type(self[lName]) == "string" then
                local tempTable = {}
                table.insert(tempTable, self[lName])
                self[lName] = tempTable
            end
            table.insert(self[lName], value)
        else
            self[lName] = value
        end
        table.insert(self.___props, { name = name, value = self[name] })
    end

    return node
end



你可能感兴趣的:(cocos2d lua集成XML教程)