souhugirl 2011-11-30
原文出处:http://www.mzone.cc/article/270.html htmlparser是一个基于java的用来解析html页面的开源组件,可以很方便对html页面进行标签分析、动态修改、删除特定的html标签等。但有些时候,我们可能需要自定义非HTML标签实现一些额外的功能,比如我经常使用htmlparser解析并处理页面后需要返回最终的处理结果,一般情况下我们获取html这个根标签,然后toHtml()就可以得到了。但如果页面本身就不规范,没有或包含多个html根标签呢?这样就会出现数据遗漏的情况,我这里就来讲下我的处理过程:
1、自定义一个根标签
2、将解析到的HTML内容使用根标签进行包裹
3、再使用htmlparser解析包裹的结果字符串并处理
4、获取自定义的根标签并返回标签内部的内容
5、输出最终的自定义标签的内部内容即可完整输出
首先,我们定义一个我们自己的html标签,在htmlparser中自定义标签需要继承CompositeTag类,该类非常简单,只需要覆写基类的getIds方法即可,如下:
package cc.mzone.html; import org.htmlparser.tags.CompositeTag; /** * 基于HtmlParser的全局顶层容器定义,包装所有的HTML内容。 * * @author 铁木箱子 * */ public class ContainerTag extends CompositeTag { private static final long serialVersionUID = -191586261848623602L; public static final String HTML_CONTAINER_TAG_NAME = "mzone-html-container"; @Override public String[] getIds() { return new String[] { HTML_CONTAINER_TAG_NAME }; } }
写完一个自定义html标签后,我们需要注册到htmlparser的解析其中,需要注意的是每个htmlparser解析器都需要单独注册额外的自定义html标签,我们这里先用自定义标签包裹要解析的html代码,然后再注册并解析根节点返回,代码片段如下:
package cc.mzone.html; import org.htmlparser.Node; import org.htmlparser.Parser; import org.htmlparser.PrototypicalNodeFactory; import org.htmlparser.filters.TagNameFilter; import org.htmlparser.util.NodeList; /** * 获取包装后的顶层HTML元素 * @param content * @return * @throws Exception */ public Node getRootNode(String content, String encoding) throws Exception { // 先用我们自定义的标签包裹需要解析的内容content StringBuilder buf = new StringBuilder(); buf.append("<" + ContainerTag.HTML_CONTAINER_TAG_NAME + ">"); buf.append(content); buf.append("</" + ContainerTag.HTML_CONTAINER_TAG_NAME + ">"); // 获取一个htmlparser的解析器 Parser parser = Parser.createParser(buf.toString(), encoding); // 注册一个已经注册了我们自定义标签的节点工厂给上面的解析器,这个是关键 PrototypicalNodeFactory nodeFactory = new PrototypicalNodeFactory(); nodeFactory.registerTag(new ContainerTag()); parser.setNodeFactory(nodeFactory); // 解析内容获取顶层标签,即我们刚自定义的标签 NodeList list = parser.parse(new TagNameFilter(ContainerTag.HTML_CONTAINER_TAG_NAME)); return list.elementAt(0); }
然后我们就可以对这个内容进行分析和处理,等分析处理完成后,就需要获取最终的处理html内容,使用如下代码片段来获取:
package cc.mzone.html; /** * 获取最终的过滤结果 * @param root * @return * @throws Exception */ public String getFinalResult(Node root) throws Exception { String result = root.toHtml(); int len = ContainerTag.HTML_CONTAINER_TAG_NAME.length(); return result.substring(len + 2, result.length() - len - 3); }
其中root节点就是我们在getRootNode中得到的根节点,也就是我们自定义的html标签,在这个方法中我们仅仅是去掉这个节点的名称而已,从而也就实现了我们想要的目标。使用这个自定义标签可以非常好的解决html格式不标准的问题,从而可以兼容更多的情况和场合。