正则表达式解析XML文档 
CSDN Blog推出文章指数概念,文章指数是对Blog文章综合评分后推算出的,综合评分项分别是该文章的点击量,回复次数,被网摘收录数量,文章长度和文章类型;满分100,每月更新一次。
这段时间做中移动的一些接口,看到那些"标准接口"心里不知道是什么感觉.连笑都懒得笑了.
一个连26个字母都认不全的人,说我要做英语同声翻译,说这种话除了需要天大的勇气,其它的只能说是无知了.连一些java的基础语法都不能正确应用,竟然写出给"中国移动"这种绝对企业级应用的接口,中兴公司开发的MM7接口,看了以后每一个有良心的程序员都有想自杀的感觉.
算了,不提它了.
目前在java平台上,要解析xml文档,即使只有"<abc></abc>"这样的一个标签,在生成document对象时,也至少要花费300ms左右,这样一次交互至少要在600ms左右,加上其它处理,一次通讯要1000ms以上,使得soap协议在java平台上根本不能进行实际应用.
其它这并不是SOAP协议的问题,着关键在于对XML文档的解析.基于这个原因,笔者实现了用正则表达式来解析XML文档的一些API,利用它来在替换中移动的大多数SOAP的接口,效率提高了10倍左右.
package l.regex;
import *;
import java.util.*;
/**
*
* <p>Title: Document</p>
*
* <p>Description: 用正则表达式解析xml,目的是为了提高性能.</p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: org.axman</p>
*
* @author :Axman
* @version 1.0
*/
public class Document {
private String xmlString;
/**
* 传入xml的字符串内容,对于InputStream,Reader对象请转换为String对象后传入构造方法.
* @param xmlString String
* @throws IllegalArgumentException
*/
public Document(String xmlString) throws IllegalArgumentException{
if(xmlString == null || xmlString.length() == 0)
throw new IllegalArgumentException("Input string orrer!");
}
/**
* 在文档中搜索指定的元素,返回符合条件的元素数组.
* @param tagName String
* @return String[]
*/
public String[] getElementsByTag(String tagName){
Pattern p = Patternpile("<"+tagName+"[^>]*?((>.*?</"+tagName+">)|(/>))");
Matcher m = p.lString);
ArrayList<String> al = new ArrayList<String>();
while(m.find())
al.up());
String[] arr = al.toArray(new String[al.size()]);
al.clear();
return arr;
}
/**
* 用xpath模式提取元素,以#为分隔符
* 如 ROOT#PARENT#CHILD表示提取ROOT元素下的PARENT元素下的CHILD元素
* @param singlePath String
* @return String
*/
public String getElementBySinglePath(String singlePath){
String[] path = singlePath.split("#");
String lastTag = path[path
.length-1];
String tmp = "(<"+lastTag+"[^>]*?((>.*?</"+lastTag+">)|(/>)))";
//最后一个元素,可能是<x>v</x>形式或<x/>形式
for(int i=path.length-2;i >=0;i--){
lastTag = path[i];
tmp = "<"+lastTag+">.*"+tmp + ".*</"+lastTag+">";
}
Pattern p = Patternpile(tmp);
Matcher m = p.lString);
if(m.find()){
up(1);
}
return "";
}
/**
* 用xpath模式提取元素从多重元素中获取指批定元素,以#为分隔符
* 元素后无索引序号则默认为0: ROOT#PARENT[2]#CHILD[1]
* @param singlePath String
* @return String
*/
public String getElementByMultiPath(String singlePath){
try{
String[] path = singlePath.split("#");
String input = lString;
String[] ele = null;
for (int i = 0; i < path.length; i++) {
Pattern p = Patternpile("(\\w+)(\\[(\\d+)\\])?");
Matcher m = p.matcher(path[i]);
if (m.find()) {
String tagName = m.group(1);
System.out.println(input + "----" + tagName);
int index = (m.group(3) == null) ? 0 :
new up(3)).intValue();
ele = getElementsByTag(input, tagName);
input = ele[index];
}
}
return input;
}catch(Exception e){
return null;
}
}
/**
* 在给定的元素中搜索指定的元素,返回符合条件的元素数组.对于不同级别的同名元素限制作用,即可以
* 搜索元素A中的子元素C.而对于元素B中子元素C则过虑,通过多级限定可以准确定位.
* @param parentElementString String
* @param tagName String
* @return String[]
*/
public static String[] getElementsByTag(String parentElementString,String tagName){
Pattern p = Patternpile("<"+tagName+"[^>]*?((>.*?</"+tagName+">)|(/>))");
Matcher m = p.matcher(parentElementString);
ArrayList<String> al = new ArrayList<String>();
while(m.find())
al.up());
String[] arr = al.toArray(new String[al.size()]);
al.clear();
return arr;
}
/
**
* 从指定的父元素中根据xpath模式获取子元素,singlePath以#为分隔符
* 如 ROOT#PARENT#CHILD表示提取ROOT元素下的PARENT元素下的CHILD元素
* @param parentElementString String
* @param singlePath String
* @return String
*/
public static String getElementBySinglePath(String parentElementString,String singlePath){
String[] path = singlePath.split("#");
String lastTag = path[path.length-1];
String tmp = "(<"+lastTag+"[^>]*?((>.*?</"+lastTag+">)|(/>)))";
/
/最后一个元素,可能是<x>v</x>形式或<x/>形式
for(int i=path.length-2;i >=0;i--){
lastTag = path[i];
tmp = "<"+lastTag+">.*"+tmp + ".*</"+lastTag+">";
}
Pattern p = Patternpile(tmp
);
Matcher m = p.matcher(parentElementString);
if(m.find()){
up(1);
}
return "";
}
/**
* 用xpath模式提取元素从指定的多重元素中获取指批定元素,以#为分隔符
* @param parentElementString String
* @param singlePath String
* @return String
*/
public static String getElementByMultiPath(String parentElementString,String singlePath){
try{
String[] path = singlePath.split("#");
String input = parentElementString;
String[] ele = null;
for (int i = 0; i < path.length; i++) {
Pattern p = Patternpile("(\\w+)(\\[(\\d+)\\])?");
Matcher m = p.matcher(path[i]);
if (m.find()) {
String tagName = m.group(1);
int index = (m.group(3) == null) ? 0 :
new up(3)).intValue();
ele = getElementsByTag(input, tagName);
input = ele[index];
}
}
return input;
}catch(Exception e){
return null;
}
}
/**
* 在给定的元素中获取所有属性的集合.该元素应该从getElementsByTag方法中获取
* @param elementString String
* @return HashMap
*/
public HashMap<String,String> getAttributes(String elementString){
HashMap hm = new HashMap<String,String>();
Pattern p = Patternpile("<[^>]+>");
Matcher m = p.matcher(elementString);
String tmp = m.find()?m.group():"";
p = Patternpile("(\\w+)\\s*=\\s*\"([^\"]+)\"");
m = p.matcher(tmp);
while(m.find()){
hm.up(1).trim(),m.group(2).trim());
}
return hm;
}
/**
* 在给定的元素中获取指定属性的值.该元素应该从getElementsByTag方法中获取
* @param elementString String
* @param attributeName String
* @return String
*/
public static String getAttribute(String elementString,String attributeName){
HashMap hm = new HashMap<String,String>();
Pattern p = Patternpile("<[^>]+>");
Matcher m = p.matcher(elementString);
String tmp = m.find()?m.group():"";
字符串转数组 csdnp = Patternpile("(\\w+)\\s*=\\s*\"([^\"]+)\"");
m = p.matcher(tmp);
while(m.find()){
up(1).trim().equals(attributeName))
up(2).trim();
}
return "";
}
/**
* 获取指定元素的文本内容
* @param elementString String
* @return String
*/
public static String getElementText(String elementString){
Pattern p = Patternpile(">([^<>]*)<");
Matcher m = p.matcher(elementString);
if(m.find()){
up(1);
}
return "";
}
public static void main(String[] args){
new Document("<ROOT>sss <PARENT>sss <CHILD>aaaa</CHILD>ss </PARENT>sss </ROOT>").getElementByMultiPath("ROOT[0]#PARENT#CHILD");
//System.out.println(child);
}
}
Trackback: tb.blog.csdn/TrackBack.aspx?PostId=420910
[收藏到我的网
摘]  [发送Trackback]  axman发表于 2005年07月11日 14:15:00
特别推荐:
想在这里投放广告?点击查看详情
关闭
*
*
*
*
*
上一篇: 多线程编程 基础篇 (三) | 下一篇: 多线程编程 基础篇 (二)
评论
#  maxq 发表于2005-07-29 11:36:00  IP: 61.186.252.*
代码不错, 但是没有实现标准的接口啊. 为何不在标准的DOM或者SAX接口上实现呢? 另外一些XML Parser有没有你说的那么慢啊?
Pattern每次编译也会耗资源的, 而且Pattern一旦生成可以供多线程并发访问, 可以将一些共用Pattern 缓存起来. 另外String.split中间也会生成Pattern, 不如直接使用Pattern.split. 相信速度还会有所提高.
有话好好说, 不要拍我哦~~
#  maxq 发表于2005-08-01 16:52:00  IP: 61.186.252.*
我也遇到过这个问题, 是先转义再处理的. 能否说说你另外的优化方法是???
#  axman 发表于2005-08-01 11:21:00  IP: 61.186.252.*
这段代码当时因为急于调用那些接口,写出来马上主用了.其实在后来的应用中进行了很多优化,包括表达式本身进行了更准确,更精良的优化,以及一些包装方法.
对于JDK的split和replace,因为本身采用了正则表达式,对特殊字符不能完全达到你想要的效果,比如有些时候你想替换\为 &,而在JAVA中先要表示成\\,然后因表达式的匹配的转义,最后一个\成了\\\\\\\\才能表达,所以我也写了另外的优化方法.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。