【问题标题】:JSoup: Replacing a String adds new linesJSoup:替换字符串会添加新行
【发布时间】:2011-06-24 05:10:10
【问题描述】:

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”。我遇到的问题是,在最后一个导入语句和关闭的 &lt;/style&gt; 标记之间有很多新行,以前没有。

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

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

【问题讨论】:

  • 我实际上遇到了与 jsoup 完全相同的问题。我想它是 jsoup 通过插入额外的 HTML 来验证文档来试图变得“聪明”。我没有适合你的解决方案。我最终改用了 jericho HTML 解析器。

标签: java jsoup


【解决方案1】:

好吧,我今天登陆这个页面是想做一件非常相似的事情,我相信我已经解决了。希望一个月后有人还在看这个。 ;)

我发现效果很好的是,不是在每个循环上进行字符串替换和重新解析文档,而是重建style 元素的内容。 JSoup 真正大放异彩的地方之一是它的 API 让编辑已解析的文档变得多么容易。

另一个技巧是使用data() 函数。 JSoup 区分数据(例如 scriptstyle)和 html/文本节点。主要区别在于 HTML 转义应用于数据节点。

将所有这些放在一起,以下代码 sn-p 应该将您导入的样式表引用替换为您的 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()));
}

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

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

public static final Pattern CSS_IMPORT_PATTERN = Pattern.compile("(@import\\s+(?:url)?\\s*\\(?\\s*['\"]?)(.*?)([\\s'\";,)]|$)");

【讨论】:

  • 嗨,不清楚“base.toExternalForm()”的来源。您能否显示实例化“base”的代码部分,以便清楚这是什么类型的对象。谢谢!
  • 我明白了。尽管我的问题涉及在样式块中保留引号“文字”,但此解决方案有助于解决问题。 +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-14
  • 2022-11-17
  • 1970-01-01
  • 2019-01-11
  • 1970-01-01
  • 2016-04-05
相关资源
最近更新 更多