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

简介:

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

  例如要从

  1. <pre name="code" class="java">data=<div><div>abcd<div></div><form>
  2. <input type='button' value='submit'/></form></div></div><div>1234</div>

  中取出<div></div>之间的内容,希望返回两个字符串

  1. <pre name="code" class="java"><div>abcd<div></div><form>
  2. <input type='button' value='submit'/></form></div><pre name="code" class="html">和1234

  源代码如下:

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

  1. public class Tag {  
  2.       
  3.     public Tag(String value, int beginPos, int endPos) {  
  4.         super();  
  5.         this.value = value;  
  6.         this.beginPos = beginPos;  
  7.         this.endPos = endPos;  
  8.     }  
  9.     private String value;  
  10.     private int beginPos;  
  11.     private int endPos;  
  12.     public String getValue() {  
  13.         return value;  
  14.     }  
  15.     public void setValue(String value) {  
  16.         this.value = value;  
  17.     }  
  18.     public int getBeginPos() {  
  19.         return beginPos;  
  20.     }  
  21.     public void setBeginPos(int beginPos) {  
  22.         this.beginPos = beginPos;  
  23.     }  
  24.     public int getEndPos() {  
  25.         return endPos;  
  26.     }  
  27.     public void setEndPos(int endPos) {  
  28.         this.endPos = endPos;  
  29.     }  
  30.       
  31. }

  从字符串中获取节点之间内容的函数如下:

  1.        /** 
  2.  * 获取字符串之间的内容,如果包含嵌套,则返回最外层嵌套内容 
  3.  *  
  4.  * @param data       
  5.  * @param stag      起始节点串 
  6.  * @param etag      结束节点串 
  7.  * @return 
  8.  */ 
  9. public List<String> get(String data,String stag, String etag){  
  10.     // 存放起始节点,用于和结束节点匹配 
  11.     Stack<Tag> work = new Stack<Tag>();  
  12.     // 保存所有起始和结束节点 
  13.     List<Tag> allTags = new ArrayList<Tag>();  
  14.       
  15.     // 在元字符前加转义符 
  16.     String nstag = stag.replaceAll("([\\*\\.\\+\\(\\]\\[\\?\\{\\}\\^\\$\\|\\\\])""\\\\$1");  
  17.     String netag = etag.replaceAll("([\\*\\.\\+\\(\\]\\[\\?\\{\\}\\^\\$\\|\\\\])""\\\\$1");  
  18.       
  19.     String reg = "((?:"+nstag+")|(?:"+netag+"))";  
  20.       
  21.     Pattern p = Pattern.compile(reg, Pattern.CASE_INSENSITIVE|Pattern.MULTILINE);  
  22.       
  23.     Matcher m = p.matcher(data);  
  24.       
  25.     while(m.find()){  
  26.         Tag tag = new Tag(m.group(0),m.start(),m.end());  
  27.         allTags.add(tag);  
  28.     }  
  29.     // 保存开始结束节点之间的内容,不含节点 
  30.     List<String> result = new ArrayList<String>();  
  31.       
  32.     for(Tag t : allTags){  
  33.         if (stag.equalsIgnoreCase(t.getValue())){  
  34.             work.push(t);  
  35.         }else if(etag.equalsIgnoreCase(t.getValue())){  
  36.             // 如果栈已空,则表示不匹配 
  37.             if (work.empty()){  
  38.                 throw new RuntimeException("pos "+t.getBeginPos()+" tag not match start tag.");  
  39.             }  
  40.             Tag otag = work.pop();  
  41.             // 如果栈为空,则匹配 
  42.             if (work.empty()){  
  43.                 String sub = data.substring(otag.getEndPos(), t.getBeginPos());  
  44.                 result.add(sub);  
  45.             }  
  46.         }  
  47.           
  48.     }  
  49.       
  50.     // 如果此时栈不空,则有不匹配发生 
  51.     if (!work.empty()){  
  52.         Tag t = work.pop();  
  53.         throw new RuntimeException("tag "+t.getValue()+ "not match.");  
  54.     }  
  55.       
  56.     return result;  
  57.       
  58. }

  函数返回节点之间内容串组成的列表。

  例如 调用 get(data,"<div>", "</div>") 返回含有两个元素的列表,元素分别为

<div>abcd<div></div><form><input type='button' value='>'/></form></div>, 1234

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


本文出自seven的测试人生公众号最新内容请见作者的GitHub页:http://qaseven.github.io/

目录
相关文章
|
1月前
|
算法 Java 开发者
Java 项目实战数字华容道与石头迷阵游戏开发详解及实战方法
本文介绍了使用Java实现数字华容道和石头迷阵游戏的技术方案与应用实例,涵盖GUI界面设计、二维数组操作、游戏逻辑控制及自动解法算法(如A*),适合Java开发者学习游戏开发技巧。
179 46
|
2月前
|
安全 Java API
Java 集合高级应用与实战技巧之高效运用方法及实战案例解析
本课程深入讲解Java集合的高级应用与实战技巧,涵盖Stream API、并行处理、Optional类、现代化Map操作、不可变集合、异步处理及高级排序等核心内容,结合丰富示例,助你掌握Java集合的高效运用,提升代码质量与开发效率。
182 0
|
2月前
|
算法 搜索推荐 Java
Java中的Collections.shuffle()方法及示例
`Collections.shuffle()` 是 Java 中用于随机打乱列表顺序的方法,基于 Fisher-Yates 算法实现,支持原地修改。可选传入自定义 `Random` 对象以实现结果可重复,适用于抽奖、游戏、随机抽样等场景。
87 0
|
2月前
|
安全 Java
JAVA:Collections类的shuffle()方法
`Collections.shuffle()` 是 Java 中用于随机打乱列表顺序的工具方法,适用于洗牌、抽奖等场景。该方法直接修改原列表,支持自定义随机数生成器以实现可重现的打乱顺序。使用时需注意其原地修改特性及非线程安全性。
91 0
|
2月前
|
算法 安全 Java
java中Collections.shuffle方法的功能说明
`Collections.shuffle()` 是 Java 中用于随机打乱列表顺序的方法,基于 Fisher-Yates 算法实现,常用于洗牌、抽奖等场景。可选 `Random` 参数支持固定种子以实现可重复的随机顺序。方法直接修改原列表,无返回值。
87 0
|
Java
JAVA方法的定义
JAVA方法的定义
180 0
|
6月前
|
存储 JSON Java
《从头开始学java,一天一个知识点》之:方法定义与参数传递机制
**你是否也经历过这些崩溃瞬间?** - 看了三天教程,连`i++`和`++i`的区别都说不清 - 面试时被追问&quot;`a==b`和`equals()`的区别&quot;,大脑突然空白 - 写出的代码总是莫名报NPE,却不知道问题出在哪个运算符 🚀 这个系列就是为你打造的Java「速效救心丸」!我们承诺:每天1分钟,地铁通勤、午休间隙即可完成学习;直击痛点,只讲高频考点和实际开发中的「坑位」;拒绝臃肿,没有冗长概念堆砌,每篇都有可运行的代码标本。上篇:《输入与输出:Scanner与System类》 | 下篇剧透:《方法重载与可变参数》。
127 25
|
安全 Java 编译器
杭州 【Java基础知识 11】java泛型方法的定义和使用(学习+改进+自己理解,想法) (借鉴-侵-删)
杭州 【Java基础知识 11】java泛型方法的定义和使用(学习+改进+自己理解,想法) (借鉴-侵-删)
106 1
|
存储 Java
Java数组与带参数方法:定义、调用及实践
Java数组与带参数方法:定义、调用及实践
163 1
|
存储 Java
Java中带返回值方法的定义与调用技术
Java中带返回值方法的定义与调用技术
221 1

热门文章

最新文章