分享关于j2me xmlReader的轻量级实现

发表于:2007-06-22来源:作者:点击数: 标签:
一、kxml的前身--xmlpull xmlpull提供了为资源有限的环境(如j2me)和j2ee应用 服务器 使用的xml解析API,xml pull解析允许使用stream解析的方式。 xmlpull的特点: * 简单的接口-解析器包含一个接口、一个异常、一个建立解析器的factory; * 无实现依赖-模

   
  一、kxml的前身--xmlpull
  
  xmlpull提供了为资源有限的环境(如j2me)和j2ee应用服务器使用的xml解析API,xml pull解析允许使用stream解析的方式。
  
  xmlpull的特点:
  

  * 简单的接口-解析器包含一个接口、一个异常、一个建立解析器的factory;
  
  * 无实现依赖-模仿JAXP的factory类和很容易的切换不同的XmlPull V1 API实现,而无需修改代码;
  
  * 易用性-只有唯一的next()方法用来读取下面5类事件中的一个:
  
  START DOCUMENT-文档起始点,这时解析器还没有准备好读取文档;
  
  START_TAG-解析器读取到了element声明的开始标签,就是xml文件中声明element用的"<";
  
  TEXT-解析器读取到了element的内容,如element的各种属性和value;
  
  END_TAG-解析器读取到了element声明的结束标签,就是"/>"或者"</...>";
  
  END_DOCUMENT-解析器读取到文档的结尾,解析工作完毕。
  
  * 多功能性-由于提供了xml解析器的通用接口,所以允许多个实现和在特性和属性上的扩展
  
  * 良好的性能-由于提供了通用的接口,可以说也就为使用快速的xml解析器提供了条件,但是目前最快的解析器,本人还没遇到过。:-)
  
  * 最小化需要-设计上与j2me兼容,从而使其能工作于小型设备和建立使用微量内存的xmlPull兼容的解析器。
  
  二、建立在良好构架上的kxml
  
  xmlpull api提供的通用的xml内容解析功能使用方式:使用一个循环来遍历到下一个事件,并切换到一个针对这个事件的分支语句处理。但是在使用xml解析器时,一些xml element不仅包括text还有其它的element(被称为子元素或者内嵌元素)。对于这样的xml数据,解析处理被简单化到了使用xmlpull api的nextTag和nextText方法。另外,require方法也可以使用一个解析状态的参数来表示希望取得数据的event类型。以上就是kxml使用方法。
  
  如解析下面内容的简单xml文件:
  <elements>
  <text>text1</text>
  <text>text2</text></elements>
  
  解析代码片断如下:
  parser.nextTag();parser.require(XmlPullParser.START_TAG, null, "elements");
  while(parser.nextTag() == XmlPullParser.START_TAG) { parser.require(XmlPullParser.START_TAG, null, "text");
  // handle element content  System.out.println("text content: "+ parser.nextText());
  parser.require(XmlPullParser.END_TAG, null, "text");}parser.require(XmlPullParser.END_TAG, null, "elements");
  
  从上面的代码看出,的确很简单明了。
  
  三、背向kxml的原因
  
  但是如果真正的使用kxml开发j2me程序时会发现,kxml包和其依赖的xmlpull包不仅无形中增加了程序发布时的大小,而且由于没有最好的解析器带来的负面性能损耗会随着xml文件的大小成非线性增长(还好不是指数级的)。这些成为了kxml的流行障碍。
  
  四、轻量级的xmlReader
  
  幸运的是kobject.org网站上提供了一个轻量级的xmlReader程序,大家可以到http://kobjects.sourceforge.net/utils/ 获取。
  
  作为简单的xml解析器,功能上与kxml类似,但是不支持命名空间和一些传统的事件。整个jar文件大小小于5KB。
  
  以下便是其代码:
  XmlReader.java
  /* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or
  * sell copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE. */package org.kobjects.xml;import java.io.*;
  import java.util.*;
  /** A minimalistic XML pull parser, similar to kXML, but
  not supporting namespaces or legacy events. If you need
  support for namespaces, or aclearcase/" target="_blank" >ccess to XML comments or
  processing instructions, please use kXML(2) instead. */public class XmlReader {
  /** Return value of getType before first call to next() */
  public final static int START_DOCUMENT = 0;
  /** Signal logical end of xml document */
  public final static int END_DOCUMENT = 1;
  /** Start tag was just read */  public final static int START_TAG = 2;
  /**   * End tag was just read
  */
  public final static int END_TAG = 3;
  /** Text was just read */
  public final static int TEXT = 4;
  final static int CDSECT = 5;
  final static int ENTITY_REF = 6;
  static final private String UNEXPECTED_EOF =
  "Unexpected EOF";
  static final private int LEGACY = 999;
  // general  public boolean relaxed;
  private Hashtable entityMap;
  private int depth;
  private String[] elementStack = new String[4];
  // source  private Reader reader;
  private char[] srcBuf =
  new char[Runtime.getRuntime().freeMemory() >= 1048576
  ? 8192
  : 128];
  private int srcPos;
  private int srcCount;
  private boolean eof;
  private int line;
  private int column;
  private int peek0;
  private int peek1;
  // txtbuffer
  private char[] txtBuf = new char[128];
  private int txtPos;
  // Event-related
  private int type;
  private String text;
  private boolean isWhitespace;
  private String name;
  private boolean degenerated;
  private int attributeCount;
  private String[] attributes = new String[16];
  private String[] TYPES =
  {
  "Start Document",
  "End Document",
  "Start Tag",
  "End Tag",
  "Text" };
  private final int read() throws IOException {
  int r = peek0;
  peek0 = peek1;
  if (peek0 == -1) {
  eof = true;
  return r;
  }    else if (r == '\n' || r == '\r') {
  line++;
  column = 0;
  if (r == '\r' && peek0 == '\n')
  peek0 = 0;    }
  column++;
  if (srcPos >= srcCount) {
  srcCount = reader.read(srcBuf, 0, srcBuf.length);
  if (srcCount <= 0) {
  peek1 = -1;
  return r;
  }
  srcPos = 0;
  }
  peek1 = srcBuf[srcPos++];
  return r;
  }
  private final void exception(String desc)
  throws IOException {
  throw new IOException(
  desc + " pos: " + getPositionDescription());
  }
  private final void push(int c) {
  if (c == 0)
  return;
  if (txtPos == txtBuf.length) {
  char[] bigger = new char[txtPos * 4 / 3 + 4];
  System.arraycopy(txtBuf, 0, bigger, 0, txtPos);
  txtBuf = bigger;
  }
  txtBuf[txtPos++] = (char) c;
  }  private final void read(char c) throws IOException {
  if (read() != c) {
  if (relaxed) {
  if (c <= 32) {
  skip();
  read();
  }
  }
  else {
  exception("expected: '" + c + "'");
  }
  }
  }
  private final void skip() throws IOException {
  while (!eof && peek0 <= ' ')
  read();
  }
  private final String pop(int pos) {
  String result = new String(txtBuf, pos, txtPos - pos);
  txtPos = pos;
  return result;
  }
  private final String readName() throws IOException {
  int pos = txtPos;    int c = peek0;
  if ((c < 'a' || c > 'z')
  && (c < 'A' || c > 'Z')
  && c != '_'
  && c != ':'
  && !relaxed)

原文转自:http://www.ltesting.net