背景
背景:我们的后台系统发布一个内容的时候在数据库里是一个html片段,类似于"<div><p class="..."><div class="...">content, <a src="...""
需要写一个java类,输入是一个上述html片段,将所有的指向图片的<a>标签的src修改为另一个src值,另外一个src值的构成是
path+原src值中的文件名,path是传入的一个参数
要完成一个java类,有一个公有方法
StringrecaculateImage(String htmlDiv, String path)
由于这是一个共用的方法务必注意
1)必须是线程安全的
2)除了常量不允许有static类型的成员变量
3)只能处理图片类型的<a>标签,(你可以列举常用的图片类型)
4)务必考虑各种可能性,保障尽可能所有情况下都能正确工作
第一次尝试
遇到这种情况,第一个反应就是正则表达式,找到相关的正则表达式,然后找出匹配的,再做替换。然后开工:几经尝试之后,写出如下代码:
首先是找<a>标签中有src中有图片格式的,然后找出来之后提取图片的文件名,然后再进行补全。
public String recaculateImage(String htmlDiv, String path)
{
String regxpForTag = "\\s*a\\s+([^>]*)\\s*src=\"([^\"](?i).+?\\.(jpg|gif|bmp))\""; //找出<a>标签中src属性为jpg,gif,bmp
Pattern patternForTag = Pattern.compile(regxpForTag);
Matcher matcherForTag = patternForTag.matcher(htmlDiv);
StringBuffer sb = new StringBuffer();
boolean result = matcherForTag.find();
while(result){
String fileName = matcherForTag.group(0).substring(matcherForTag.group(0).lastIndexOf("\\")+1); //取出符合条件的文件名称
matcherForTag.appendReplacement(sb, "a src=\""+ path + fileName);
result = matcherForTag.find();
}
matcherForTag.appendTail(sb);
return sb.toString();
}
但是,后来发现有一个问题,因为这样只能对于<a>标签中只有一个属性值的情况下是可以生效的,如果有其他属性值的话,提取出来会有问题,需要对取文件名称的语句进行调整,同时,更严重的问题是提取的html片段若是不完整的,也不会补全,这样必然会影响处理后的效果。
第二次尝试
然后,是否有更好的办法呢?html片段,如果能转换成XHTML,然后在DOM对象中找到相应的节点进行操作,这样是否会更简便?
思路就是HTML先转化为XHTML,然后通过xpath,xquery对相应节点进行操作。
然后搜索了下,主要有Jtidy,NekoHTML,htmlparser等。
各种都有过尝试,最后采用了htmlparser,代码如下:主要还是找到对应节点,然后在节点内对内容进行操作,这样的正则表达式就不需要这么复杂了。
/**
*
* 基本功能:将所有的指向图片的<a>标签的src修改为另一个src值
* <p>
*
* @param htmlDiv
* @param path
* <a>标签中src属性的文件处理后的路径
* @如:替换<a>标签的src属性值的路径
*/
public String recaculateImage(String htmlDiv, String path) throws ParserException{
StringBuilder filterContent = new StringBuilder();
Parser parser = new Parser(htmlDiv);
String regxpForTagAttrib = "src=\"([^\"](?i).+?\\.(jpg|gif|bmp))\""; //找出<src>属性中为有jpg、gif、bmp等图片的
// 遍历所有的节点
NodeList nodes = parser.extractAllNodesThatMatch(new NodeFilter() {
public boolean accept(Node node) {
return true;
}
});
for (int i = 0; i < nodes.size(); i++) {
Node node = nodes.elementAt(i);
if (node instanceof LinkTag) { //找出<a>标签
LinkTag lnk = (LinkTag) nodes.elementAt(i);
String src = lnk.getText();
Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib);
Matcher matcherForTag = patternForAttrib.matcher(node.getText());
boolean result = matcherForTag.find();
if(result)
{
String fileName =lnk.getAttribute("src").substring(lnk.getAttribute("src").lastIndexOf("\\")+1);//找出文件名称
lnk.setAttribute("src", path+fileName);//进行更新路径
}
else
{
System.out.println("不符合:"+src);
}
filterContent.append('<');
filterContent.append(node.getText());
filterContent.append('>');
} else if (node instanceof TextNode) {
TextNode text = (TextNode) node;
filterContent.append(text.getText());
} else {
filterContent.append('<');
filterContent.append(node.getText());
filterContent.append('>');
}
}
return filterContent.toString();
}
然后htmlparser有很多jar包
我用的是下面的
http://download.csdn.net/detail/cryptlordx/8060313