htmlparser中自定义html标签进行解析

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格式不标准的问题,从而可以兼容更多的情况和场合。

相关推荐