构建轻量级XMLDOM分析程序

XML正迅快速的成为数据存储和交换的标准格式流行开来了。现在可用的完整的Java XML分析器非常庞大而且功能强大--但是实现这些强大的功能的同时也要消耗等量的资源。

公司主营业务:成都网站建设、成都做网站、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出锦江免费做网站回馈大家。

因此使用一个功能强大的XML分析器可能过于浪费。如果配置环境是一个Java小程序或者是一个J2ME应用程序,网络带宽或者系统存储器的制约可能根本不能够使用完整的XML分析器。本文将告诉你如何构建一个轻量级的XML DOM分析程序。

开始编写SimpleDOMParser

SimpleDOMParser是一个使用Java写的高度简化和超轻量级的XML DOM分析器。 你可以将配置整个分析器配置为一个小于4KB的.jar文件。源程序还不到400行呢。

显然,使用这么小的代码,SimpleDOMParser将不支持XML域名空间,不能够理解多字符集编码或者以DTD文件或者schema验证文件;但是SimpleDOMParser能做的就是把符合语法规则的XML标记解析为一个类似于DOM的元素树,让你执行从XML格式化文本提取的数据的公共任务。

为什么使用DOM作为模型而不是SAX呢?这是因为DOM提供一个比SAX更加易用的程序接口。与SAX不同的是,当你把一个XML文件作为一个DOM树来处理的时候,这个文件内的所有的信息都是可以利用的。虽然SAX分析模型能够提供比DOM模型更加优异的性能和利用更少的存储空间,但是大部分开发者在使用SAX的时候都会发现他们自己正在创建一个完整的或者部分的DOM树。

使用SAX,一个应用程序每次只能处理一条标记。如果其它的标记内容在处理的过程中必须被用到,那你就必须在处理的整个过程保持一种全局状态。而保持全局状态正是DOM模型目的的精髓。但是许多小型的XML应用程序不需要完整的DOM模型。因此,SimpleDOMParser提供到标记名、层次和内容的访问,但是不涉及完整的W3C DOM的许多用不上的功能。

简化DOM模型

一个DOM树是由分析XML文件产生的结点组成。结点是一个XML实体的非存储表现。标准W3C DOM模型有几种类型的结点。 举例来说,一个文本结点表示在XML文件中的一段文本,一个元素结点表示XML文件而一个属性结点表示一个元素内部的属性名和值。

DOM是一个树,因为除了根或文件结点以外的每个结点都有一个父结点。举例来说,属性结点总是和一个元素结点相关联,而用来封装元素的起始标记和结束标记中的文本是映射到一个文本结点的。文本结点是元素结点的一个子节点。所以,即使很简单的XML文件的表现也可能会需要很多种节点类型。举例来说,图1表示下面XML文件的一个W3C DOM树形表示。

 
 
 
  1. <parser>SimpleDOMParser</parser>

正如你在图1中所看见的,DOM模型使用一个document类型节点来封装整个XML文件,所以DOM使用三种不同的节点。通过把所有的DOM节点类型抽象成为一个单独的类型SimpleElement来尽可能的简化DOM模型。一个SimpleElement获得一个XML元素的关键的信息,比如标识名、元素属性和任何封装的文本或者XML。此外,SimpleDOMParser不使用任何特殊的节点类型表示***等级的文档。结果是大大地简化了DOM树,使之只包含SimpleElement节点。图2表示了简化的DOM树。

代码段1给出了SimpleElement类的完整的源程序。

 
 
 
  1. public class SimpleElement {
  2. private String tagName;
  3. private String text;
  4. private HashMap attributes;
  5. private LinkedList childElements;
  6. public SimpleElement(String tagName) {
  7. this.tagName = tagName;
  8. attributes = new HashMap();
  9. childElements = new LinkedList();
  10. }
  11. public String getTagName() {
  12. return tagName;
  13. }
  14. public void setTagName(String tagName) {
  15. this.tagName = tagName;
  16. }
  17. public String getText() {
  18. return text;
  19. }
  20. public void setText(String text) {
  21. this.text = text;
  22. }
  23. public String getAttribute(String name) {
  24. return (String)attributes.get(name);
  25. }
  26. public void setAttribute(String name, String value) {
  27. attributes.put(name, value);
  28. }
  29. public void addChildElement(SimpleElement element) {
  30. childElements.add(element);
  31. }
  32. public Object[] getChildElements() {
  33. return childElements.toArray();
  34. }
  35. }  

#p#

定义XML语法分析基本元素

为了把一个XML文件处理成为上面提到的简化的DOM树模型,我们必须定义一些基本的语法分析规则。使用这些规则,语法分析程序就能容易地从输入的XML文件中提取标记或者文本块。

***个是peek,从输入的XML文件中返回下一个字符,而实际上则不必从下层流中获得这个字符。通过保持输入流的完整性,高级函数比如readTag和readText(后面将介绍)可以更加容易地根据它们接下来期待的字符获取需要的内容。

 
 
 
  1. private int peek() throws IOException { 
  2. reader.mark(1); 
  3. int result = reader.read(); 
  4. reader.reset(); 
  5. return result; 
  6. }  

下一个方法是skipWhitespce,作用是跳过输入的XML流中的空格、制表符或者回车符。

 
 
 
  1. private void skipWhitespace() throws IOException { 
  2. while (Character.isWhitespace((char) peek())) { 
  3. reader.read(); 

在创建了如上所述的这两个方法后,我们就可以写一个函数从输入文件中检索XML标记。

 
 
 
  1. private String readTag() throws IOException { 
  2. skipWhitespace(); 
  3. StringBuffer sb = new StringBuffer(); 
  4. int next = peek(); 
  5. if (next != '<') { 
  6. throw new IOException 
  7. ("Expected > but got " + (char) next); 
  8. sb.append((char)reader.read()); 
  9. while (peek() != '>') { 
  10. sb.append((char)reader.read()); 
  11. sb.append((char)reader.read()); 
  12. return sb.toString(); 

和peek方法联合使用,readTag函数只获得一个标记的内容,而让别的函数去处理其他的内容。 ***的一个方法是readText函数,用来读取XML标记之间的文本。

 
 
 
  1. private String readText() throws IOException { 
  2. int[] cdata_start = {'<', '!', 
  3. '[', 'C', 'D', 'A', 'T', 'A', '['}; 
  4. int[] cdata_end = {']', ']', '>'}; 
  5. StringBuffer sb = new StringBuffer(); 
  6. int[] next = new int[cdata_start.length]; 
  7. peek(next); 
  8. if (compareIntArrays(next, cdata_start) == true) { 
  9. // CDATA 
  10. reader.skip(next.length); 
  11. int[] buffer = new int[cdata_end.length]; 
  12. while (true) { 
  13. peek(buffer); 
  14. if (compareIntArrays 
  15. (buffer, cdata_end) == true) { 
  16. reader.skip(buffer.length); 
  17. break; 
  18. } else { 
  19. sb.append((char)reader.read()); 
  20. } else { 
  21. while (peek() != '<') { 
  22. sb.append((char)reader.read()); 
  23. return sb.toString(); 
  24. }  

这次使用的peek方法是前面那个从基本的XML文档返回一个字符串序列的peek方法的变体。这个peek变体让语法分析程序判断它将分析的文本是否被装入一个CDATA块。compareIntArrays函数是一个执行两个整数数组的深度比较的简单程序。

#p#

定义XML语法分析基本元素

为了把一个XML文件处理成为上面提到的简化的DOM树模型,我们必须定义一些基本的语法分析规则。使用这些规则,语法分析程序就能容易地从输入的XML文件中提取标记或者文本块。

***个是peek,从输入的XML文件中返回下一个字符,而实际上则不必从下层流中获得这个字符。通过保持输入流的完整性,高级函数比如readTag和readText(后面将介绍)可以更加容易地根据它们接下来期待的字符获取需要的内容。

 
 
 
  1. private int peek() throws IOException { 
  2. reader.mark(1); 
  3. int result = reader.read(); 
  4. reader.reset(); 
  5. return result; 
  6. }  

下一个方法是skipWhitespce,作用是跳过输入的XML流中的空格、制表符或者回车符。

 
 
 
  1. private void skipWhitespace() throws IOException { 
  2. while (Character.isWhitespace((char) peek())) { 
  3. reader.read(); 

在创建了如上所述的这两个方法后,我们就可以写一个函数从输入文件中检索XML标记。

 
 
 
  1. private String readTag() throws IOException { 
  2. skipWhitespace(); 
  3. StringBuffer sb = new StringBuffer(); 
  4. int next = peek(); 
  5. if (next != '<') { 
  6. throw new IOException 
  7. ("Expected > but got " + (char) next); 
  8. sb.append((char)reader.read()); 
  9. while (peek() != '>') { 
  10. sb.append((char)reader.read()); 
  11. sb.append((char)reader.read()); 
  12. return sb.toString(); 

和peek方法联合使用,readTag函数只获得一个标记的内容,而让别的函数去处理其他的内容。 ***的一个方法是readText函数,用来读取XML标记之间的文本。

 
 
 
  1. private String readText() throws IOException { 
  2. int[] cdata_start = {'<', '!', 
  3. '[', 'C', 'D', 'A', 'T', 'A', '['}; 
  4. int[] cdata_end = {']', ']', '>'}; 
  5. StringBuffer sb = new StringBuffer(); 
  6. int[] next = new int[cdata_start.length]; 
  7. peek(next); 
  8. if (compareIntArrays(next, cdata_start) == true) { 
  9. // CDATA 
  10. reader.skip(next.length); 
  11. int[] buffer = new int[cdata_end.length]; 
  12. while (true) { 
  13. peek(buffer); 
  14. if (compareIntArrays 
  15. (buffer, cdata_end) == true) { 
  16. reader.skip(buffer.length); 
  17. break; 
  18. } else { 
  19. sb.append((char)reader.read()); 
  20. } else { 
  21. while (peek() != '<') { 
  22. sb.append((char)reader.read()); 
  23. return sb.toString(); 
  24. }  

这次使用的peek方法是前面那个从基本的XML文档返回一个字符串序列的peek方法的变体。这个peek变体让语法分析程序判断它将分析的文本是否被装入一个CDATA块。 compareIntArrays函数是一个执行两个整数数组的深度比较的简单程序。

分享标题:构建轻量级XMLDOM分析程序
分享地址:http://www.mswzjz.cn/qtweb/news17/8167.html

攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能