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

    xiaoxiao2022-07-16  156

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

      例如要从

    <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>之间的内容,希望返回两个字符串

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

      源代码如下:

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

    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;       }        }

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

           /**  * 获取字符串之间的内容,如果包含嵌套,则返回最外层嵌套内容  *   * @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>") 返回含有两个元素的列表,元素分别为

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

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

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

    相关资源:java处理字符串搜索嵌套结构的方法.docx
    最新回复(0)