7

我正在使用 Java 中的有效 HTML 字符串(使用 jsoup 解析,因此所有标签都有结束标签并且格式正确),我需要找到给定标签名称的内容,例如,使用以下内容细绳:

<p> hi! </p>
<p> hi again! </p>
<h1> foo </h1>
<p> bye! </p>

给定标签“p”,我期望的结果是:

1)<p> hi! </p>
2)<p> hi again! </p>
3)<p> bye! </p>

我通过简单地使用 apache.commons.lang 库和 StringUtils.substringsBetween(String html, String "opentag" , String "endtag") 方法来完成此操作,该方法将返回具有所需结果的字符串数组。但是,当我搜索一个包含完全相同标签的标签时(一个常见的例子是 div),我会得到错误的结果(我明白为什么)

例如,与...合作

<div>
 <p> hey there </p>
 <div>  
  <div>
   <p> asd </p>
  </div>
 </div>
</div>

我希望得到 3 个结果:1)

<div>
 <p> hey there </p>
 <div>  
  <div>
   <p> asd </p>
  </div>
 </div>
</div>

2)

<div>  
 <div>
  <p> asd </p>
 </div>
</div>

3)

<div>
 <p> asd </p>
</div>

但是我得到了一个(我知道它是因为标签的出现如何出现在字符串中)我只是不知道如何解决它。我已经为此苦苦挣扎了 2 周,我尝试过使用正则表达式,但完全没有成功,我还尝试将 html 字符串拆分为行数组,但也失败了。

你会如何处理这个问题?我已经知道有很多库可以使用 jsoup 的 getAllElementsByTag(tagName) 等方法为您执行此操作,但我想自己做。任何提示表示赞赏!

4

3 回答 3

1

一个标准的方法是使用堆栈。即,当您遇到一个开始标签时,您将转储到堆栈中,并且每当您遇到一个结束标签时,您弹出最顶层的项目。如果字符串确实格式正确,则所有结束标记都应弹出匹配的开始标记。从那里开始,弄清楚如何获取内部对的内容应该是小菜一碟。

于 2013-06-03T16:45:31.503 回答
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;
        }
    }
}

这是一个非常粗略的草图并且存在一些问题,特别是如果您的标签没有被新行或空格与其内容分隔(就像在您的示例中那样)。正如您所说,它还假设 HTML 格式正确。但这足以让我们理解这个想法。声明的ArrayList<String>将包含所有<div>标签及其内容。

于 2013-06-03T16:33:42.413 回答
0

TagSoup或者Jsoup将是您正在寻找的那个:)

于 2014-05-08T14:15:29.473 回答