加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 教程 > 正文

Java处理字符串搜索嵌套结构的技巧

发布时间:2021-12-17 13:57:49 所属栏目:教程 来源:互联网
导读:在用Java分析HTML文本时,如果要取出有嵌套结构的节点之间的内容,不能直接用正则表达式来处理,因为java所带的正则表达式不支持嵌套结构的描述,虽然Perl、.Net、PHP可以支持。这时可以先用正则表达式找出节点在字符串中的位置,然后对节点进行匹配处理,取

在用Java分析HTML文本时,如果要取出有嵌套结构的节点之间的内容,不能直接用正则表达式来处理,因为java所带的正则表达式不支持嵌套结构的描述,虽然Perl、.Net、PHP可以支持。这时可以先用正则表达式找出节点在字符串中的位置,然后对节点进行匹配处理,取出匹配节点之间的内容,实现对嵌套结构的处理。
 
例如要从
 
[html]
<pre name="code" class="java">data=<div><div>abcd<div></div><form><input type='button' value='submit'/></form></div></div><div>1234</div>  
中取出<div></div>之间的内容,希望返回两个字符串
[html]
<pre name="code" class="java"><div>abcd<div></div><form><input type='button' value='submit'/></form></div><pre name="code" class="html">和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<String> get(String data,String stag, String etag){  
    // 存放起始节点,用于和结束节点匹配   
    Stack<Tag> work = new Stack<Tag>();  
    // 保存所有起始和结束节点   
    List<Tag> allTags = new ArrayList<Tag>();  
      
    // 在元字符前加转义符   
    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<String> result = new ArrayList<String>();  
      
    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,"<div>", "</div>") 返回含有两个元素的列表,元素分别为
 
[html]
<div>abcd<div></div><form><input type='button' value='>'/></form></div>, 1234  
需要注意的是如果节点含有正则表达式的元字符,需要在元字符前加转义符,源代码中第16,17行实现此功能。

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读