JSoup:替换字符串会添加新行

时间:2011-05-18 09:30:22

标签: java jsoup

我对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>标记之间有很多新的行,而之前没有。

为什么会出现这种情况以及如何避免这种情况的任何线索?

很抱歉格式错误,但我似乎在发布时删除了我的代码的某些部分。第一个代码块周围有一个样式标记...

1 个答案:

答案 0 :(得分:2)

好吧,今天我登陆这个页面寻找做类似的事情,我相信我已经解决了。希望有人现在仍在观看这个,这是一个月之后。 ;)

我发现效果很好的是,不是在每个循环上进行字符串替换和重新解析文档,而是重建style元素的内容。 JSoup真正发挥作用的地方之一就是它的API编辑解析文档的难易程度。

另一个技巧是使用data()函数。 JSoup区分数据(例如scriptstyle)和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'\";,)]|$)");