java處理字串搜尋嵌套結構的方法

來源:互聯網
上載者:User

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

例如要從

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

中取出<div></div>之間的內容,希望返回兩個字串

<div>abcd<div></div><form><input type='button' value='submit'/></form></div>
和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

需要注意的是如果節點含有Regex的元字元,需要在元字元前加轉義符\\,原始碼中第16,17行實現此功能。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.