歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java處理字符串搜索嵌套結構的方法

Java處理字符串搜索嵌套結構的方法

日期:2017/3/1 10:33:46   编辑:Linux編程

在用java分析HTML文本時,如果要取出有嵌套結構的節點之間的內容,不能直接用正則表達式來處理,因為java所帶的正則表達式不支持嵌套結構的描述,雖然Perl、.Net、PHP可以支持。這時可以先用正則表達式找出節點在字符串中的位置,然後對節點進行匹配處理,取出匹配節點之間的內容,實現對嵌套結構的處理。

例如要從

[html]
  1. <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] 
  1. <pre name="code" class="java"><div>abcd<div></div><form><input type='button' value='submit'/></form></div><pre name="code" class="html">和1234。

源代碼如下:

為了記錄節點在字符串中的值和位置,先定義一個類,保存這些信息:

[java]
  1. public class Tag {
  2. public Tag(String value, int beginPos, int endPos) {
  3. super();
  4. this.value = value;
  5. this.beginPos = beginPos;
  6. this.endPos = endPos;
  7. }
  8. private String value;
  9. private int beginPos;
  10. private int endPos;
  11. public String getValue() {
  12. return value;
  13. }
  14. public void setValue(String value) {
  15. this.value = value;
  16. }
  17. public int getBeginPos() {
  18. return beginPos;
  19. }
  20. public void setBeginPos(int beginPos) {
  21. this.beginPos = beginPos;
  22. }
  23. public int getEndPos() {
  24. return endPos;
  25. }
  26. public void setEndPos(int endPos) {
  27. this.endPos = endPos;
  28. }
  29. }
從字符串中獲取節點之間內容的函數如下:

[java]
  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. String nstag = stag.replaceAll("([\\*\\.\\+\\(\\]\\[\\?\\{\\}\\^\\$\\|\\\\])", "\\\\$1");
  16. String netag = etag.replaceAll("([\\*\\.\\+\\(\\]\\[\\?\\{\\}\\^\\$\\|\\\\])", "\\\\$1");
  17. String reg = "((?:"+nstag+")|(?:"+netag+"))";
  18. Pattern p = Pattern.compile(reg, Pattern.CASE_INSENSITIVE|Pattern.MULTILINE);
  19. Matcher m = p.matcher(data);
  20. while(m.find()){
  21. Tag tag = new Tag(m.group(0),m.start(),m.end());
  22. allTags.add(tag);
  23. }
  24. // 保存開始結束節點之間的內容,不含節點
  25. List<String> result = new ArrayList<String>();
  26. for(Tag t : allTags){
  27. if (stag.equalsIgnoreCase(t.getValue())){
  28. work.push(t);
  29. }else if(etag.equalsIgnoreCase(t.getValue())){
  30. // 如果棧已空,則表示不匹配
  31. if (work.empty()){
  32. throw new RuntimeException("pos "+t.getBeginPos()+" tag not match start tag.");
  33. }
  34. Tag otag = work.pop();
  35. // 如果棧為空,則匹配
  36. if (work.empty()){
  37. String sub = data.substring(otag.getEndPos(), t.getBeginPos());
  38. result.add(sub);
  39. }
  40. }
  41. }
  42. // 如果此時棧不空,則有不匹配發生
  43. if (!work.empty()){
  44. Tag t = work.pop();
  45. throw new RuntimeException("tag "+t.getValue()+ "not match.");
  46. }
  47. return result;
  48. }
函數返回節點之間內容串組成的列表。

例如 調用 get(data,"<div>", "</div>") 返回含有兩個元素的列表,元素分別為

[html]
  1. <div>abcd<div></div><form><input type='button' value='>'/></form></div>, 1234
需要注意的是如果節點含有正則表達式的元字符,需要在元字符前加轉義符\\,源代碼中第16,17行實現此功能。
Copyright © Linux教程網 All Rights Reserved