2012-03-26 64 views
0

在Java中,我有一個任意的HTML文檔作爲字符串。爲簡單起見,說:轉換前後的字符串索引

String original = "Hello, <strong>this</strong> is a string"; 

和我有不同的位置的記錄字符串中,始終在文本中,而不是一個標籤內。例如,單詞「is」的開頭和結尾的索引是29和31.

然後,我對字符串執行轉換 - 在這種情況下刪除HTML標籤。這使得:

original = "Hello, this is a string"; 

有沒有得到詞的新的開始和結束索引的一種優雅的方式「是」現在(12和14)?

我能想到的一種可能的解決方案是在每個原始索引處插入一個「標誌」,剝離HTML,然後在記錄其位置時移除標誌。這不應該導致HTML剝離問題,因爲索引總是出現在標籤之外。

如果這實際上是最好的方法,沒有人有任何建議,以確定選擇「標誌」,絕對不會巧合發生在任何HTML文件?

+0

任何你不能說的理由:startNew = startOld - (lengthNew - lengthOld)? – mfrankli 2012-03-26 15:24:48

+0

@mfrankli我認爲我的示例有點過於簡化了 - 實際上,在所需的索引後面可能會出現其他html標記,這些html標記在刪除後會阻止將字符串長度的變化等同於距字符串開頭的距離。 – 2012-03-26 15:29:19

回答

1

最好的方法將取決於你如何剝離HTML標籤。如果您只是刪除括在<>括號中的所有內容,那麼您可以循環訪問舊字符串,並保留舊索引前方括號內的所有內容。沿着這些線的東西可能會工作:

public String newIndex(String str, int oldIndex) { 
    int newIndex = 0; 
    boolean inBracket = false; 
    for (int i = 0; i < str.length(); i++) { 
    if (i == oldIndex) return newIndex; 
    char c = str.charAt(i); 
    if (c == '<') inBracket = true; 
    else if (c == '>') inBracket = false; 
    else if (!inBracket) newIndex++; 
    } 
    return newIndex; 
} 
+0

感謝這個例子。理想情況下,我想使用JSoup之類的東西去除HTML,因爲它包含空白標準化和html實體解碼,但這絕對是一種可能性。 – 2012-03-26 15:43:47

+0

正如在另一個答案中提到的,如果將其摺疊到刪除HTML標籤的過程中,您會獲得更好的性能。但是手工操作非常困難,你一定會遇到意想不到的情況。如果你手頭有一個庫去掉標記,並且可以從中找出索引,我肯定會推薦這條路線。 – Alex 2012-03-26 15:59:04

1

當你去掉每個標籤時,你顯然知道剛剛移除的標籤的長度。對於每個這樣的標籤,查找全部字索引值,它們是後面的,比剛刪除的標籤的索引值。對於任何找到的,從索引中減去標籤的長度。這會在您刪除標籤時使索引保持同步,從而使任務遠遠比試圖在最後計算調整更簡單。

+0

不錯。一個缺點是我不能再使用像JSoup這樣的東西來刪除HTML,我必須通過正則表達式自己做。此外,我有一種感覺,這不會那麼高效,但這對我來說不是一個大問題。 – 2012-03-26 15:35:51

+0

你最初如何獲得單詞索引?你可以不簡單地收集他們* *剝離標籤後?你說得對,效率在那裏不會很好,但除非你有一個巨大的HTML源代碼或大量的這樣的頁面來工作,否則這種差異可能不會傷害用戶。 – JTeagle 2012-03-26 15:40:52

1

不是真的。主要問題是String是最終的(所以你不能擴展這個類),並且大多數使用String的地方,CharSequence就足夠了(你實際上可以創建你自己的實現)。

所以,你有兩個選擇:

  1. 創建你自己的HTML剝離HTML標籤

後,再次剝離代碼

  • 重新編制文件,如果你只需要剝去HTML,那麼你可以使用這個正則表達式:<[^>]+>這是保證工作,除非你有CDATA blocks(你可以通過查找<![CDATA[)或內嵌JavaScript(查找<script>標籤沒有src屬性)。