在Java中查找嵌套匹配的HTML标记

ant*_*lli 7 html java tags jsoup

我在Java中使用有效的HTML字符串(使用jsoup解析,因此所有标签都有结束标记并且形成良好),我需要查找给定标记名称的内容,例如,使用以下内容串:

<p> hi! </p>
<p> hi again! </p>
<h1> foo </h1>
<p> bye! </p>
Run Code Online (Sandbox Code Playgroud)

鉴于标签'p',我期望的结果是:

1)<p> hi! </p>
2)<p> hi again! </p>
3)<p> bye! </p>
Run Code Online (Sandbox Code Playgroud)

我通过简单地使用apache.commons.lang库和StringUtils.substringsBetween(String html,String"opentag",String"endtag")方法来完成这一点,该方法将返回一个具有所需结果的String数组.但是,当我搜索嵌套了完全相同标签的标签时(常见的例子是div)我会得到错误的结果(我理解为什么)

例如,使用...

<div>
 <p> hey there </p>
 <div>  
  <div>
   <p> asd </p>
  </div>
 </div>
</div>
Run Code Online (Sandbox Code Playgroud)

我期待3个结果:1)

<div>
 <p> hey there </p>
 <div>  
  <div>
   <p> asd </p>
  </div>
 </div>
</div>
Run Code Online (Sandbox Code Playgroud)

2)

<div>  
 <div>
  <p> asd </p>
 </div>
</div>
Run Code Online (Sandbox Code Playgroud)

3)

<div>
 <p> asd </p>
</div>
Run Code Online (Sandbox Code Playgroud)

但是我得到一个(我知道它是因为标签出现在String中的方式)我只是不知道如何解决它.我现在已经苦苦挣扎了两个星期了,我已经尝试过使用正则表达式而没有任何成功,我也尝试将html字符串拆分为一系列行,但也失败了.

你会如何解决这个问题?我已经知道有很多库使用jsoup的getAllElementsByTag(tagName)等方法为你做这件事,但我想自己做.任何提示都表示赞赏!

ast*_*eri 1

您将需要大量使用标记化和递归来解决此问题。本质上,每次打开新标签(例如<div>)时,您都会再次启动处理。

考虑如下:

ArrayList<String> elements = new ArrayList<String>();
Scanner scanner = new Scanner(html);

public String populateDivContents(String buildingString) {

    while(scanner.hasNext()) {

        //Get the next token
        String next = scanner.next();

        //If it's a <div>, call recursively
        if(next.equalsIgnoreCase("<div>")) {
            buildingString = buildingString + populateDivContents(next);
        }

        //If we've hit a closing tag, add our built String to the elements
        else if(next.equalsIgnoreCase("</div>") {
            buildingString = buildingString + next;
            elements.add(buildingString);
            return buildingString;
        }

        //Otherwise, simply add the text to our String and keep going
        else {
            buildingString = buildingString + next;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个非常粗略的草图,存在一些问题,特别是如果您的标签与其内容之间没有用换行符或空格分隔(如示例中所示)。正如您所说,它还假设 HTML 格式良好。但这足以让人们理解这个想法。声明的内容ArrayList<String>将包含所有<div>标签及其内容。