美文网首页
Wax框架简明教程(4)Wax HTTP+XML示例

Wax框架简明教程(4)Wax HTTP+XML示例

作者: 祥子_HelloWorld | 来源:发表于2019-08-03 00:53 被阅读0次

本来是想介绍“Building NativeiOS Apps with Wax: Creating a Sample Application”一文的第二部分,它介绍了一个从iOS获取twitter主题的Wax Application实现过程。其中,twitter的数据是用JSON封装的 。

但很不幸,由于众所周知的原因,国内的用户无法直接访问twitter的服务器 。 因此我修改了这个例子,改为用HTTP+XML的,服务器端用java实现,在调试时你可以把服务端放在本地,这样就不受网络限制。同时,服务器数据改用XML封装。因为在我的经验中,XML使用的概率远大于JSON。

但问题在于,wax_http中没有针对XML格式数据进行实现。你可以查看它的源代码,它只实现了:text、json、binary三种format。如果你使用json,那么在wax_http中根本不需要涉及json解析,正如“Building NativeiOS Apps with Wax: Creating a Sample Application”的例子所示,一切都是透明的。

因此我们就只能自己进行XML解析。本文采用的是“Luaonly XML parser”方式。这种实现最早源自AlexanderMakeeve,后面又衍生出了许多版本。

我们在github上找到了其中一个版本,是CoronaXML Module的修改版本,叫做:LuaSimple XML Parser
这个XML parser只有一个simpleXml.lua文件,使用起来很方便——将它拷贝到你的工程目录中就可以使用了。

一、服务端

作为示例,服务端的代码足够简单,它就是directory.jsp:

<%// 重要,否则出现乱码%>
<%@ page contentType="text/html; charset=utf-8" language="java" errorPage=""%>
<%
Stringuser=request.getParameter("user");
Stringpass=request.getParameter("pass");
out.println("<?xmlversion=\"1.0\" encoding=\"utf-8\" ?>");
if(user!=null || pass!=null){
Stringxml="<list><deptname='行政部' id='01'><linkman id='001'name='郭书全'/>"+
"<linkman id='003' name='雅各布'/>"+
"</dept>"+"<dept name='人力部' id='02'><linkman id='002' name='王有福'>"+
"</linkman></dept></list>";
System.out.println(xml);
// response.setCharacterEncoding("utf-8");
out.println(xml);
}else{
out.println("<login><status>false</status></login>");
}
%>

代码基本上是静态的,你把它的HTML代码保存为.htm文件也不会有什么问题。

二、Wax实现

新建Single ViewApplication工程。加入Wax框架。关于Wax框架的安装,你可以参考“XCode 4.2下Wax的安装步骤”一文。

接下来我们准备实现一个WaxApplication。首先是main.m文件:

#import <UIKit/UIKit.h>
#import "wax.h"
#import "wax_http.h"
#import "wax_xml.h"
#import "wax_filesystem.h"
intmain(int argc, char *argv[]) {
    NSAutoreleasePool * pool =[[NSAutoreleasePoolalloc] init];
    wax_start("AppDelegate.lua", luaopen_wax_http, luaopen_wax_xml, luaopen_wax_filesystem, nil);
    int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");
    [pool release];
    return retVal;
}

注意代码中的“wax_xml.h”和“luaopen_wax_xml”。原来是“wax_json.h”和“luaopen_wax_json”。我们原来是想用wax.xml代替wax.json来着,但由于wax虽然实现了wax.xml,但在wax_http中根本没有使用,实际上“wax_xml.h”和“luaopen_wax_xml”在这里没有任何意义。

然后是AppDelegate.lua:

require "MyTableViewController"
waxClass{"AppDelegate", protocols = {"UIApplicationDelegate"}}
function applicationDidFinishLaunching(self, application)
    local frame = UIScreen:mainScreen():bounds()
    self.window =UIWindow:initWithFrame(frame)
   self.controller = MyTableViewController:init()
local nc=UINavigationController:initWithRootViewController(self.controller)
    self.window:setRootViewController(nc)
   self.window:makeKeyAndVisible()
end

应用程序启动时没有直接加载MyTableViewController,而是用一个NavigationController来加载MyTableViewController。这样可以为我们提供一个额外的NavigationBar。

最后是MyTableViewController.lua的实现:

require("xmlSimple")
waxClass{"MyTableViewController", UITableViewController}

function init(self)
    self.super:initWithStyle(UITableViewStyleGrouped)
    self.trends ={}
    return self
end

function viewDidLoad(self)
   self:setTitle("Wax Http+XML示例")
    self:tableView():setAllowsSelection(false)
    local button =UIBarButtonItem:initWithBarButtonSystemItem_target_action(UIBarButtonSystemItemRefresh,self, "loadDataFromTwitter")
    self:navigationItem():setRightBarButtonItem(button)
end

functionloadDataFromTwitter(self)
   UIApplication:sharedApplication():setNetworkActivityIndicatorVisible(true)-- show spinner
    wax.http.request{"http://localhost:8080/AnyMail/directory.jsp?user=1&pass=1",callback = function(body, response)
       UIApplication:sharedApplication():setNetworkActivityIndicatorVisible(false)-- hide spinner
       local xml = xmlSimple:newParser()
       local parseXml=xml:ParseXmlText(body)
        if response:statusCode() == 200 then
            self.trends = {} -- Reset the list oftrends when the trends are refreshed
           --[[]]
            for index,value in ipairs(parseXml.list.dept) do -- iterateover a table with numerical keys
                table.insert(self.trends, "+"..value["@name"]) -- append the value to the "array"
               linkman=value.linkman
               puts(#linkman)
               if linkman~=nil then
                   if #linkman>0 then
                       for i,v in ipairs(linkman) do
                           table.insert(self.trends,"    -"..v["@name"])
                       end
                   else
                       table.insert(self.trends,"    - "..linkman["@name"])
                   end
               end
           end
        end
        self:tableView():reloadData()
    end}
end

function numberOfSectionsInTableView(self,tableView)
    return 1
end

function tableView_numberOfRowsInSection(self,tableView, section)
    return #self.trends
end

functiontableView_titleForHeaderInSection(self, tableView, section)
    if section == 0 then
        return"企业通讯录"
    end
    return nil
end

function tableView_cellForRowAtIndexPath(self,tableView, indexPath)
    local identifier = "TwitterTableViewControllerCell"
    local cell =tableView:dequeueReusableCellWithIdentifier(identifier) or
UITableViewCell:initWithStyle_reuseIdentifier(UITableViewCellStyleDefault,identifier)
    local object = self.trends[indexPath:row()+ 1] -- Must +1 because Lua arrays are 1 based
    cell:textLabel():setText(object)
    return cell
end

代码不多,你直接把它们粘贴到文件里就可以运行了。许多代码比如TableViewDataSource方法的实现,在前面“Wax框架简明教程(2)”中你已经熟悉了。我们主要关注的是 loadDataFromTwitter 函数(函数名还没改过来...)。

首先,当然要 require("simpleXml")。然后构建一个simpleXml对象:

local xml =xmlSimple:newParser()

然后用ParseXmlText方法把xml字符串转变为一张lua表:

localparseXml=xml:ParseXmlText(body)

在我们的例子里,我们的XML文件内容是:

<?xml version="1.0"encoding="utf-8" ?>
<list>
<dept name='行政部' id='01'>
<linkmanid='001' name='郭书全'/>
<linkmanid='003' name='雅各布'/>
</dept>
<dept name='人力部' id='02'>
<linkmanid='002' name='王有福'></linkman>
</dept>
</list>

如果你想访问第2个dept节点的第一个linkman子节点,那么用parseXml.dept[2].linkman就可以了。转化成lua表是这样的(只是parseXml.dept[2].linkman这点节点,如果打印整张表的内容,那就太多了):

{
 addProperty = function: 0x6a6f050,
  @id ="002",
  numProperties= function: 0x6a68200,
  numChildren= function: 0x6a71a30,
  properties= function: 0x6a681e0,
  @name= "王有福",
  addChild = function: 0x6a71a50,
  ___children = {
  },
  setName = function: 0x6a6f5a0,
  name = function: 0x6a6f0b0,
  ___name = "linkman",
  value = function: 0x6a71db0,
  ___props = {
    1 = {
        name = "id",
    },
    2 = {
        name = "name",
       value = function: 0x6a6f0b0,
    },
  },
  children = function: 0x6a191d0,
  setValue = function: 0x6a6f010,
}

接下来的事情,就是遍历Lua表,这是Lua分内的事情,就不用我多说了。值得一提的是,针对某个节点的子节点有3种可能情况,以dept下的linkman为例:

  1. 该子节点不存在。这样的话,dept[i].linkman返回nil;
  2. 该子节点有多个。这样的话,dept[i].linkman返回一个数字索引的数组(Lua表),数组每个元素又是一个lua表(包含linkman的所有属性和值);
  3. 该子节点只有一个。这样的话,dept[i].linkman仍然返回一个lua表,但这个lua表直接包含了linkman所有属性、值等信息。

也就说,2、3两种情况的处理方法不同。对于单个子节点,我们可以直接以linkman[i]或linkman[k]的方式访问到linkman的属性。而对于多个子节点,linkman[i]只能访问到一张lua表(不能用linkman[k]来访问,因为此时linkman只包含数字键索引,不会包括文本键索引),然后通过这张lua表的index或key才能访问到linkman的属性。

参考:http://blog.csdn.net/kmyhy/article/details/8048138

相关文章

网友评论

      本文标题:Wax框架简明教程(4)Wax HTTP+XML示例

      本文链接:https://www.haomeiwen.com/subject/fudldctx.html