cocos2d lua集成XML教程

本文介绍了一个用于Lua的简单XML解析器模块,该模块能够轻松地解析和读取XML文件。文章提供了安装步骤及使用示例,展示了如何通过简单的API调用来加载XML字符串或文件,并获取其中的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

</pre>Installation</h1><ol class="task-list" style="padding:0px 0px 0px 2em; margin-top:0px; margin-bottom:16px; color:rgb(51,51,51); font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif; font-size:16px; line-height:25.600000381469727px"><li style="">Copy the xmlSimple.lua file to your project.</li><li style="">Create a local variable <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace; font-size:14px; padding:0.2em 0px; margin:0px">local xml = require("xmlSimple.lua").newParser()</code></li><li style="">Read xml using <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace; font-size:14px; padding:0.2em 0px; margin:0px">xml:ParseXmlText(xmlString)</code> or <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace; font-size:14px; padding:0.2em 0px; margin:0px">xml:loadFile(xmlFilename, base)</code></li></ol><h1 style="font-size:2.25em; margin:1em 0px 16px; line-height:1.2; position:relative; padding-bottom:0.3em; border-bottom-width:1px; border-bottom-style:solid; border-bottom-color:rgb(238,238,238); color:rgb(51,51,51); font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif"><a target=_blank target="_blank" name="user-content-parsing-xml" class="anchor" href="https://github.com/Cluain/Lua-Simple-XML-Parser#parsing-xml" style="color:rgb(65,131,196); text-decoration:none; position:absolute; top:0px; bottom:0px; left:0px; display:block; padding-right:6px; padding-left:30px; margin-left:-30px; background:transparent"></a>Parsing XML</h1><div class="highlight highlight-xml" style="margin-bottom:16px; color:rgb(51,51,51); font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif; font-size:16px; line-height:25.600000381469727px"><pre style="overflow:auto; font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace; font-size:14px; margin-top:0px; margin-bottom:0px; padding:16px; line-height:1.45; word-wrap:normal; word-break:normal; background-color:rgb(247,247,247)"><span class="nt" style="color:navy"><test</span> <span class="na" style="color:teal">one=</span><span class="s" style="color:rgb(221,17,68)">"two"</span><span class="nt" style="color:navy">></span>
    <span class="nt" style="color:navy"><three</span> <span class="na" style="color:teal">four=</span><span class="s" style="color:rgb(221,17,68)">"five"</span> <span class="na" style="color:teal">four=</span><span class="s" style="color:rgb(221,17,68)">"six"</span><span class="nt" style="color:navy">/></span>
    <span class="nt" style="color:navy"><three></span>eight<span class="nt" style="color:navy"></three></span>
    <span class="nt" style="color:navy"><nine</span> <span class="na" style="color:teal">ten=</span><span class="s" style="color:rgb(221,17,68)">"eleven"</span><span class="nt" style="color:navy">></span>twelve<span class="nt" style="color:navy"></nine></span>
<span class="nt" style="color:navy"></test></span>

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值