服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

无线开发:如何使用kxml解析wap


  一、两种访问方法:
  
  目前的kxml支持两种wap格式:wbxml/wml。
  
  而有两种方法将解析wbxml:
  
  1。使用j2me将wbxml转换到xml;
  
  2。使用kxml直接解析wbxml流。下面我在这里讨论一下使用第二种方法实现client代码解析wbxml,当然要使用kxml了。
  
  二、kxml实现方法:
  
  首先需要位于web server的应用程序通过开放wap网关(关于jwap:详见http://jwap.sourceforge.net/)发送wml文件给j2me client。在wap网关将数据发送j2me client之前wap网关将wml文件转换为了wbxml文件。下面代码的展示了j2me client如何接收wbxml数据,解析数据,并显示有用的数据在手机屏幕上。
  
  需要注意,在本例程中使用的kxml v1.0版本,kxml v2.0版本在使用上可能有所不同,开发者可以参考kxml2的手册。
  
  import java.io.*;
  import org.kxml.*;
  import org.kxml.parser.*;
  import org.kxml.wap.*;
  import javax.microedition.lcdui.*;
  import javax.microedition.midlet.*;
  import javax.microedition.io.*;
  public class wbxmltest extends midlet implements commandlistener
  {  private display display = null;  private list menu = null;
  private form form = null;
  private string incomingtext = "";
  static final command okcommand
  = new command("ok",
  command.ok,
  1);
  static final command exitcommand
  = new command("exit",
  command.exit,
  0);
  // this is a hard coded wsp message that contains
  // address of web server where our jsp page is located.
  byte[] message ={
  (byte)'1',(byte)0x40,(byte)0x3d,(byte)'h',(byte)'t',
  (byte)'t',(byte)'p',(byte)':',(byte)'/',(byte)'/',
  (byte)'l',(byte)'o',(byte)'c',(byte)'a',(byte)'l',
  (byte)'h',(byte)'o',(byte)'s',(byte)'t',(byte)':',
  (byte)'8',(byte)'0',(byte)'8',(byte)'0',(byte)'/',
  (byte)'e',(byte)'x',(byte)'a',(byte)'m',(byte)'p',
  (byte)'l',(byte)'e',(byte)'s',(byte)'/',(byte)'j',
  (byte)'s',(byte)'p',(byte)'/',(byte)'f',(byte)'i',
  (byte)'n',(byte)'a',(byte)'l',(byte)'f',(byte)'i',
  (byte)'l',(byte)'e',(byte)'s',(byte)'/',(byte)'d',
  (byte)'a',(byte)'t',(byte)'.',(byte)'j',(byte)'s',
  (byte)'p',(byte)0x80,(byte)0x94,(byte)0x88,(byte)0x81,
  (byte)0x6a,(byte)0x04,(byte)0x83,(byte)0x99
  };
  // memory space to receive message.  byte[] msg = new byte [256];
  public void pauseapp() { /* ----- */ }
  public void destroyapp(boolean unconditional)
  { notifydestroyed(); }
  public void startapp() {
  display = display.getdisplay(this);
  this.mainmenu();
  }//startapp
  //displays the menu screen
  private void mainmenu() {
  menu = new list(" send request", choice.implicit);
  menu.append(" send message",null);
  menu.addcommand(okcommand);
  menu.setcommandlistener(this);
  display.setcurrent(menu);
  }//mainmenu
  //display the reply from wapgateway (jwap).
  private void showreply()  {
  form = new form( "incoming message" );
  form.append("the price = " + incomingtext);
  
  form.addcommand(exitcommand);
  form.setcommandlistener(this);
  display.setcurrent(form);  }//showreply
  // makes a wsp connection with a wapgateway,
  // sends a message and receives the reply.
  public void getconnect() {
  datagram dgram =null;
  datagramconnection dc=null;
  try
  {
  dc = (datagramconnection)connector.open ("datagram://127.0.0.1:9200");
  dgram = dc.newdatagram(message, message.length);
  try{
  dc.send(dgram);}
  catch (interruptedioexception e){
  e.printstacktrace(); }
  dgram = dc.newdatagram (msg,msg.length);
  try{
  dc.receive(dgram);}
  catch (interruptedioexception e){
  e.printstacktrace();}
  catch( ioexception e){
  e.printstacktrace();}
  // this is the most interesting part.
  incomingtext = this.getincomingtextofwmlc(dgram.getdata());
  this.showreply();
  dc.close();
  }//try
  catch (illegalargumentexception ie){
  ie.printstacktrace(); }
  catch (connectionnotfoundexception cnf){
  cnf.printstacktrace();  }
  catch (ioexception e){e.printstacktrace();}
  }//getconnect()
  private string getincomingtextofwmlc ( byte[] wmlc ) {
  try {
  // remove wsp header.
  // we know it is 19 bytes for our case.
  // but for real world applications,
  // this should be dynamically deteced.
  for ( int j = 0; j < wmlc.length-19; j++ )
  wmlc[j] = wmlc[j+19];
  wmlparser parser = new wmlparser(new bytearrayinputstream(wmlc));
  while (true) {
  try {
  parseevent parseevent = parser.read();
  if ( parseevent.gettype() == xml.start_tag ) {
  attribute attr =
  parseevent.getattribute("value");
  if ( attr != null )
  return attr.getvalue();
  }//if
  }//try
  catch ( ioexception e) {}
  }//while
  }//try
  catch ( ioexception e) { e.printstacktrace();  }
  return "error";
  }//getincomingtextofwmlc
  public void commandaction(command c, displayable d) {
  string commandlabel = c.getlabel();
  if (commandlabel.equals("exit"))
  destroyapp(false);
  else if (commandlabel.equals("ok"))
  getconnect();
  }//commandaction
  }//class wbxmltest
  
  为了演示目的,除了建立一个web server外,还要在本机建立一个jwap server。
  
  三、代码说明:
  
  上面的代码将数据连接请求发送到了本机的jwap server的url:“datagram://127.0.0.1:9200”,并发送了一个硬编码的wsp(wireless session protocol)请求:http://localhost:8080/examples/jsp/finalfiles/dat.jsp,然后等待并读取jwap server的回应,在接收到回应信息后使用kxml解析提取其中的数据(元素属性名为“value”的属性值)。在解析完成后,将数据显示于手机屏幕上。
  
  代码中的getconnect 方法建立与jwap server的连接,并发送请求给jwap server,要求访问web server上的http://localhost:8080/examples/jsp/finalfiles/dat.jsp,在接收到jwap server发回的请求后,getconnect方法调用getincomingtextofwmlc方法提取接收到的wbxml数据。由于j2me client与jwap server之间的通讯使用了wap协议堆栈,所以j2me client接收的数据中包含wsp头,在getincomingtextofwmlc方法中首先去掉了这个wsp头。
  
  之后,getincomingtextofwmlc方法使用kxml的事件解析机制进行了4步操作:
  
  1。传入保存wbxml数据的字节数组构造wmlparser 对象;
  
  2。调用wmlparser的read方法,找到第一个tag开始的地方;
  
  3。读取“value”属性值;
  
  4。回到第2步进行2、3之间的循环,直到找不到start_tag。
  
  四、数据流程:
  
  而在jwap网关接收到j2me client发来的硬编码请求后,将这个请求转发给了web server,本例程中的web server为http://localhost:8080。web server接收到请求后,使用一个硬编码的wml文件作为回应:
  <?xml version="1.0"?>
  <!doctype wml public "-//wapforum//dtd wml 1.1//en" "http://www.wapforum.org/dtd/wml_1.1.xml">
  <%@ page language="java" contenttype= "text/vnd.wap.wml" %>
  <wml>
  <card id="c0" newcontext="false" ordered="false">
  <input type="price" value="15224" emptyok="false"/>
  </card>
  </wml>
  
  当jwap网关接收到这个web server的wml文件后,将其转换为wbxml格式并修改其content-type编码为wbxml,最后将转换后的wbxml格式数据发给了j2me client。
  
  五、总结:
  
  使用kxml方法避免了xml与wbxml之间的相互转换,wbxml文件的格式减少了xml文件的大小,不仅可将wbxml用于wap设备,也可以用于基于web的程序与无线设备之间的通讯和数据交换。

扫描关注微信公众号