我对JSoup有以下问题。
我想解析并修改以下html代码:
<code>
<style type="text/css" media="all">
@import url("http://hakkon-aetterni.at/modules/system/system.base.css?ll3lgd");
@import url("http://hakkon-aetterni.at/modules/system/system.menus.css?ll3lgd");
@import url("http://hakkon-aetterni.at/modules/system/system.messages.css?ll3lgd");
@import url("http://hakkon-aetterni.at/modules/system/system.theme.css?ll3lgd");
</style>
</code>
我正在使用以下代码来实现:
Elements cssImports= doc.select("style");
for (Element src : cssImports) {
String regex ="url\\(\"(.)*\"\\)";
String data =src.data();
String link;
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(data);
while (m.find()){
link=m.group().substring(5,m.group().length()-2);
doc=Jsoup.parse(doc.html().replace(link, ""));
}
}
首先,它有效。所有导入的URL都替换为字符串“FOUND
”。我遇到的问题是我在最后一个import语句和关闭的</style>
标记之间有很多新的行,而之前没有。
为什么会出现这种情况以及如何避免这种情况的任何线索?
很抱歉格式错误,但我似乎在发布时删除了我的代码的某些部分。第一个代码块周围有一个样式标记...
答案 0 :(得分:2)
好吧,今天我登陆这个页面寻找做类似的事情,我相信我已经解决了。希望有人现在仍在观看这个,这是一个月之后。 ;)
我发现效果很好的是,不是在每个循环上进行字符串替换和重新解析文档,而是重建style
元素的内容。 JSoup真正发挥作用的地方之一就是它的API编辑解析文档的难易程度。
另一个技巧是使用data()
函数。 JSoup区分数据(例如script
和style
)和html /文本节点。主要区别在于HTML转义不应用于数据节点。
将所有这些放在一起,以下代码段应该用您的FOUND
文本替换导入的样式表引用,但不会更改文档的格式:
// compile the regex before entering the loop, as it's a relatively expensive operation
Pattern pattern = Pattern.compile("url\\(\"(.)*\"\\)");
for(Element styleElem : doc.getElementsByTag("style")) {
String data = styleElem.data();
StringBuffer newData = new StringBuffer();
Matcher matcher = pattern.matcher(data);
while(matcher.find()) {
matcher.appendReplacement(newData, "FOUND");
}
matcher.appendTail(newData);
styleElem.appendChild(new DataNode(newData.toString(), base.toExternalForm()));
}
P.S。我假设你已经打开了漂亮的版画。但是,由于未显示您的文档解析代码,因此请务必在解析后调用document.outputSettings().prettyPrint(false);
。
P.P.S。在我自己的代码中,我使用更宽容(并且稍微丑陋)的正则表达式来查找导入。它让用户可以省略URL声明,引号,parens等等......因为野外的HTML往往会做所有这些事情。我在我的代码中声明它如下:
public static final Pattern CSS_IMPORT_PATTERN = Pattern.compile("(@import\\s+(?:url)?\\s*\\(?\\s*['\"]?)(.*?)([\\s'\";,)]|$)");