WEB开发网
开发学院WEB开发Jsp 如何使用kxml解析WAP 阅读

如何使用kxml解析WAP

 2008-01-05 08:58:03 来源:WEB开发网   
核心提示:如何使用kxml解析WAP作者cleverpig版权声明:任何获得Matrix授权的网站,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明作者:cleverpig(http://www.matrix.org.cn/blog/cleverpig)原文:http://www.matrix.org.cn/resou
如何使用kxml解析WAP

作者cleverpig


版权声明:任何获得Matrix授权的网站,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
作者:cleverpig(http://www.matrix.org.cn/blog/cleverpig)
原文:http://www.matrix.org.cn/resource/article/43/43909_Kxml_Wap.Html
要害字:j2me,wap,kxml

一、两种访问方法:

目前的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的程序与无线设备之间的通讯和数据交换。

六、参考资源:
Compressing XML
jWAP
kxml

Tags:如何 使用 kxml

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接