匹配特定的html属性值

时间:2016-02-18 16:16:37

标签: java regex

我想匹配idclassnamefor的所有属性值!我为这个任务创建了一个简单的函数。

private Collection<String> getAttributes(final String htmlContent) {
    final Set<String> attributes = new HashSet<>();
    final Pattern pattern = Pattern.compile("(class|id|for|name)=\\\"(.*?)\\\"");
    final Matcher matcher = pattern.matcher(htmlContent);
    while (matcher.find()) {
        attributes.add(matcher.group(2));
    }
    return attributes;
}

示例html内容:

<input id="test" name="testName" class="aClass bClass" type="input" />

如何通过正则表达式拆分html类,以便获得以下结果集:

  • 测试
  • 测试名
  • ACLASS
  • bClass

有没有办法改进我的代码?我真的不喜欢循环。

2 个答案:

答案 0 :(得分:1)

如果您查看JSoup library,可以找到有用的html解析和操作工具。

例如:

Document doc = ...//create HTML document
Elements htmlElements = doc.children();
htmlElements.traverse(new MyHtmlElementVisitor());

班级MyHtmlElementVisitor只需实施NodeVisitor即可访问Node attributes

虽然你可能会为同一份工作找到一个好的正则表达式,但它有几个缺点。仅举几例:

  • 很难为每个可能的html文档找到failafe正则表达式
  • 难以阅读,因此难以发现错误并实施更改
  • 正则表达式通常不可重复使用

答案 1 :(得分:0)

Don't use regular expressions for parsing HTML.说真的,it's more complicated than you think.

如果您的文档实际上是XHTML,则可以使用XPath:

XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xpath.evaluate(
    "//@*["
        + "local-name()='class'"
        + " or local-name()='id'"
        + " or local-name()='for'"
        + " or local-name()='name'"
    + "]",
    new InputSource(new StringReader(htmlContent)),
    XPathConstants.NODESET);
int count = nodes.getLength();
for (int i = 0; i < count; i++) {
    Collections.addAll(attributes,
        nodes.item(i).getNodeValue().split("\\s+"));
}

如果它不是XHTML,您可以使用Swing的HTML解析:

HTMLEditorKit.ParserCallback callback = new HTMLEditorKit.ParserCallback() {
    private final Object[] attributesOfInterest = {
        HTML.Attribute.CLASS,
        HTML.Attribute.ID,
        "for",
        HTML.Attribute.NAME,
    };

    private void addAttributes(AttributeSet attr) {
        for (Object a : attributesOfInterest) {
            Object value = attr.getAttribute(a);
            if (value != null) {
                Collections.addAll(attributes,
                    value.toString().split("\\s+"));
            }
        }
    }

    @Override
    public void handleStartTag(HTML.Tag tag,
                               MutableAttributeSet attr,
                               int pos) {
        addAttributes(attr);
        super.handleStartTag(tag, attr, pos);
    }

    @Override
    public void handleSimpleTag(HTML.Tag tag,
                                MutableAttributeSet attr,
                                int pos) {
        addAttributes(attr);
        super.handleSimpleTag(tag, attr, pos);
    }
};

HTMLDocument doc = (HTMLDocument)
    new HTMLEditorKit().createDefaultDocument();
doc.getParser().parse(new StringReader(htmlContent), callback, true);

至于没有循环的情况,我不认为这是可能的。但无论如何,任何实现都将在内部使用一个或多个循环。