2008-12-17 63 views
1

內斷行。我正在瀏覽一組XML文件,並試圖檢測包含換行符的特定節點內的一些文本。正則表達式檢測我有一個正則表達式的麻煩一個XML節點

下面是一些樣本數據:

<item name='GenMsgText'><text>The signature will be discarded.</text></item> 

<item name='GenMsgText'><text>The signature will be discarded.<break/> 
Do you want to continue?</text></item> 

在此示例中,我要趕僅在第二點中的文本。我想出了使用第二個正則表達式的下面的解決方案,但我想知道是否可以只使用一個來做同樣的事情。

if ($content =~m{<item name='GenMsgText'>(<textlist>)?<text>(.*?)</text>}si) 
    { 
    $t = $2; 
    if ($t =~m {\n}i) 
    { 
    print G $t."\n\n"; 
    } 
} 

這是一個一次性的工具,並不意味着可以重複使用,所以我想,以避免編寫任何代碼的解析,這比幾行。此外,上面的代碼已經工作,我問這個問題的個人知識比實際使用更多。

+0

@annakata:希望分類學家的徽章? :)即使你是唯一使用這個標籤的人,你會很快得到它,我猜... – Tomalak 2008-12-17 13:09:44

回答

0

我不知道,但認爲這應該工作:

<item name='GenMsgText'>(<textlist>)?<text>(.*\n.*)</text> 
+0

沒有,這種方式比我需要的更多。 – Antoine 2008-12-17 10:48:32

3

我應該考慮使用一些SAX解析器。正則表達式太脆弱,無法處理xml輸入。

+0

這不是因爲正則表達式會很脆弱,更多的是因爲它不能以合理的方式解析嵌套結構。 – Tomalak 2008-12-17 12:58:43

5

正則表達式是不是該任務的合適的工具,它根本不能處理嵌套結構非常好。如果你有一個DOM API您的處置,這個XPath會找到合適的節點:

如果您正在尋找<break/>元素,爲您的例子表明:

//item[@name='GenMsgText']/text[break] 

「真正的」換行,是CR (爲0xD)或LF(是0xA):

//item[@name='GenMsgText']/text[contains(., '&#xD;') or contains(., '&#xA;')] 
0

的問題是,你的S模式.*?可以匹配角括號以及換行。如果正則表達式開始匹配一個不匹配的元素,沒有什麼可以阻止它繼續下一個元素的匹配嘗試。如果你知道永遠不會有尖括號中的文字,你可以限制比賽進行到這樣一個元素:

<item name='GenMsgText'><text>([^<>\n]*\n[^<>]*)</text></item> 

編輯:值得注意的是,正則表達式由Max和基比應該提供的是非常重要的應用於s模式(/ s,單線,DOTALL ...)。這就是爲什麼它們不能匹配「item」元素的末尾:爲了到達下一個元素,他們必須匹配元素之間的行分隔符。

但是,即使沒有使用/ s改性劑,如果有兩個元素,而無需在連續的流水線內部換行符(即,僅具有一個在它們之間的換行)都正則表達式可能會失敗。例如,這兩條線將被匹配爲一個:

<item name='GenMsgText'><text>foo</text></item> 
<item name='GenMsgText'><text>bar</text></item> 

在另一方面,如果有超過兩行文本?其他正則表達式恰好匹配一個換行符,所以它們會失敗。在我正則表達式,我明確地匹配第一換行,以確保有一個,但如果有更多的換行,他們將在第二字符類匹配:[^<>]*

這種東西就是爲什麼我傾向於避免使用.*.*?

0

沿着相同的路線是什麼艾倫提到的,你可以使用一個懶惰的捕獲匹配收盤文本聲明

<item name='GenMsgText'><text>(.*?\n.*?)</text></item> 

之前只能捕捉儘可能必要的,但再一次,正則表達式可能是完全出於錯誤的工具工作,你應該使用一個合適的XML解析器。