1

我对 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”。我遇到的问题是我在最后一个导入语句和</style>之前没有的封闭标签之间有很多新行。

任何线索为什么会发生这种情况以及如何避免它?

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

4

1 回答 1

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()));
}

PS 我假设你已经关闭了漂亮的打印功能。但是,由于未显示您的文档解析代码,因此请务必document.outputSettings().prettyPrint(false);在解析后调用。

PPS 在我自己的代码中,我使用了一个更宽容(也更丑陋)的正则表达式来查找导入。它让用户可以省略 URL 声明、引号、括号等...因为 HTML 往往会做所有这些事情。我在我的代码中声明如下:

public static final Pattern CSS_IMPORT_PATTERN = Pattern.compile("(@import\\s+(?:url)?\\s*\\(?\\s*['\"]?)(.*?)([\\s'\";,)]|$)");
于 2011-06-23T21:10:10.040 回答