【问题标题】:finding the number of open closed html tags in a string查找字符串中打开的闭合 html 标记的数量
【发布时间】:2020-12-17 07:54:43
【问题描述】:

我试图找出找到字符串中有效 HTML 标记数量的最佳方法。

假设标签只有当它有一个开始和结束标签时才有效

这是一个测试用例的例子

INPUT

"html": "<html><head></head><body><div><div></div></div>"

Output

"validTags":3

【问题讨论】:

  • 这能回答你的问题吗? How to validate HTML from Java?
  • &lt;br/&gt; 怎么样?
  • 不要使用正则表达式来解析 HTML。如果您能够调整一个为您验证 HTML 的库,那就太好了。

  • 无效
  • 正如建议的问题中所建议的那样,您应该使用适当的解析器,而那些可能已经有了解决方案。如果你想自己做(但你为什么要这样做?)请记住,可能有(有效的)自闭合标签,如 &lt;br/&gt;,如建议的 saka1029 和无效的情况,如 &lt;a&gt;&lt;b&gt;&lt;/a&gt;&lt;/b&gt;(其中有每个标签的结束匹配,但嵌套错误) - 还有更多您可能还没有想到的情况。

标签: java string algorithm


【解决方案1】:

如果需要解析 HTML

不要自己动手。没有必要重新发明轮子。有大量用于解析 HTML 的库。为正确的工作使用正确的工具。

将精力集中在项目的其余部分上。当然,您可以实现自己的函数来解析字符串,查找&lt;&gt;,并采取适当的行动。但是 HTML 可能比您想象的要复杂一些,或者您最终可能需要更多的 HTML 解析,而不仅仅是计算标签。

也许将来您还想计算&lt;br/&gt;&lt;br /&gt;。或者你会想要找到 HTML 树的深度。

也许您的自制代码没有考虑转义字符、嵌套标签等所有可能的组合。字符串中有多少正确的标签: &lt;a&gt;&lt;b&gt;&lt;c&gt;&lt;d e&gt;&lt;f g="&lt;h&gt;&lt;/h&gt;"&gt;&lt;i j="&lt;k&gt;" l="&lt;/k&gt;"&gt;&lt;/i&gt;&lt;/f&gt;&lt;/e d&gt;&lt;/b&gt;&lt;/c&gt;&lt;/ a &gt;

在评论中,用户 dbl 链接到一个类似的问题,其中包含指向库的链接:How to validate HTML from java ?

如果你想把开闭标签对算作一个学习项目

这是一个用伪代码提出的算法,作为递归函数:

function count_tags(s):
  tag, remainder = find_next_tag(s)
  found, inside, after = find_closing_tag(tag, remainder)
  if (found)
    return 1 + count_tags(inside) + count_tags(after)
  else
    return count_tags(inside)

示例

  • 在字符串hello &lt;a&gt;world&lt;c&gt;&lt;/c&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;上,我们会得到:
tag = "<a>"
remainder = "world<c></c></a><b></b>"
found = true
inside = "world<c></c>"
after = "<b></b>"
return 1 + count_tags("world<c></c>") + count_tags("<b></b>")
  • 在字符串&lt;html&gt;&lt;head&gt;&lt;/head&gt;:
tag = "<html>"
remainder = "<head></head>"
found = false
inside = "<head></head>"
after = ""
return count_tags("<head></head>")
  • 在字符串&lt;a&gt;&lt;b&gt;&lt;/a&gt;&lt;/b&gt;:
tag = "<a>"
remainder = "<b></a></b>"
found = true
inside = "<b>"
after = "</b>"
return 1 + count_tags("<b>") + count_tags("</b>")

【讨论】:

    【解决方案2】:

    我写了一个函数来做这个。

    static int checkValidTags(String html,String[] openTags, String[] closeTags) {
        //openTags and closeTags must have the same length;
        //This function keeps track of all opening tags.
        //and removes the opening and closing tags if the tag is closed correctly
        //It can even detect when there are labels added to the tags.
        HashMap<Character,Integer> open = new HashMap<>();
        HashMap<Character,Integer> close = new HashMap<>();
    
        //Use a start character, this is 1 because 0 would be a string terminator.
        int startChar = 1;
        for(int i = 0; i < openTags.length; i++) {
            open.put((char)startChar, i);
            close.put((char)(startChar+1), i);
            html = html.replaceAll(openTags[i],""+ (char)startChar);
            html = html.replaceAll(closeTags[i],""+(char)(startChar+1));
            startChar+=2;
        }
        List<List<Integer>> startIndexes = new ArrayList<>();
        int validLabels = 0;
        for(int i = 0; i < openTags.length; i++) {
            startIndexes.add(new ArrayList<>());
        }
        for(int i = 0; i < html.length(); i++) {
            char c = html.charAt(i);
            if(open.get(c)!=null) {
                startIndexes.get(open.get(c)).add(0,i);
            }
            if(close.get(c)!=null&&!startIndexes.get(close.get(c)).isEmpty()) {
                String closed = html.substring(startIndexes.get(close.get(c)).get(0),i);
                for(int k = 0; k < startIndexes.size(); k++) {
                    if(!startIndexes.get(k).isEmpty()) {
                        int p = startIndexes.get(k).get(0);
                        if(p > startIndexes.get(close.get(c)).get(0)) {
                            startIndexes.get(k).remove(0);
                        }
                    }
                }
                startIndexes.get(close.get(c)).remove(0);
                html.replace(closed, "");
                validLabels++;
            }
        }
        return validLabels;
        
    }
    

    要在您的示例中使用它,您可以这样做:

        String html = "<html><head></head><body><div><div></div></div>";
        
        int validTags = checkValidTags(html,new String[] {
                //Add here all the tags you are looking for.
                //Remove the trailing '>' so it can detect extra tags appended to it
                "<html","<head","<body","<div"
        }, new String[]{
                "</html>","</head>","</body>","</div>"
        });
        
        System.out.println(validTags);
    

    输出:

    3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 2016-07-24
      • 2020-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多