java处理字符串搜索嵌套结构的方法

2014-11-24 07:11:46 · 作者: · 浏览: 0
在用java分析HTML文本时,如果要取出有嵌套结构的节点之间的内容,不能直接用正则表达式来处理,因为java所带的正则表达式不支持嵌套结构的描述,虽然Perl、.Net、 PHP可以支持。这时可以先用正则表达式找出节点在字符串中的位置,然后对节点进行匹配处理,取出匹配节点之间的内容,实现对嵌套结构的处理。

例如要从

[ html]
data=
abcd
1234

中取出
之间的内容,希望返回两个字符串
[html]
abcd
和1234。 
 


源代码如下:

为了记录节点在字符串中的值和位置,先定义一个类,保存这些信息:

[java]
public class Tag {

public Tag(String value, int beginPos, int endPos) {
super();
this.value = value;
this.beginPos = beginPos;
this.endPos = endPos;
}
private String value;
private int beginPos;
private int endPos;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getBeginPos() {
return beginPos;
}
public void setBeginPos(int beginPos) {
this.beginPos = beginPos;
}
public int getEndPos() {
return endPos;
}
public void setEndPos(int endPos) {
this.endPos = endPos;
}



}

从字符串中获取节点之间内容的函数如下:
[java]
/**
* 获取字符串之间的内容,如果包含嵌套,则返回最外层嵌套内容
*
* @param data
* @param stag 起始节点串
* @param etag 结束节点串
* @return
*/
public List get(String data,String stag, String etag){
// 存放起始节点,用于和结束节点匹配
Stack work = new Stack();
// 保存所有起始和结束节点
List allTags = new ArrayList();

// 在元字符前加转义符
String nstag = stag.replaceAll("([\\*\\.\\+\\(\\]\\[\\ \\{\\}\\^\\$\\|\\\\])", "\\\\$1");
String netag = etag.replaceAll("([\\*\\.\\+\\(\\]\\[\\ \\{\\}\\^\\$\\|\\\\])", "\\\\$1");

String reg = "(( :"+nstag+")|( :"+netag+"))";

Pattern p = Pattern.compile(reg, Pattern.CASE_INSENSITIVE|Pattern.MULTILINE);

Matcher m = p.matcher(data);

while(m.find()){
Tag tag = new Tag(m.group(0),m.start(),m.end());
allTags.add(tag);
}
// 保存开始结束节点之间的内容,不含节点
List result = new ArrayList();

for(Tag t : allTags){
if (stag.equalsIgnoreCase(t.getValue())){
work.push(t);
}else if(etag.equalsIgnoreCase(t.getValue())){
// 如果栈已空,则表示不匹配
if (work.empty()){
throw new RuntimeException("pos "+t.getBeginPos()+" tag not match start tag.");
}
Tag otag = work.pop();
// 如果栈为空,则匹配
if (work.empty()){
String sub = data.substring(otag.getEndPos(), t.getBeginPos());
result.add(sub);
}
}

}

// 如果此时栈不空,则有不匹配发生
if (!work.empty()){
Tag t = work.pop();
throw new RuntimeException("tag "+t.getValue()+ "not match.");
}

return result;

}

函数返回节点之间内容串组成的列表。
例如 调用get(data,"
", "
") 返回含有两个元素的列表,元素分别为

[html]
abcd
, 1234

需要注意的是如果节点含有正则表达式的元字符,需要在元字符前加转义符\\,源代码中第16,17行实现此功能。

摘自 indexchen的专栏