2013-11-14 87 views
0

我有一些內容從XML文件中讀取:如何用另一個字符串替換特定的字符串?

page_content = doc.xpath("/somenode/body").inner_text 

此內容保存一些數據:

<p> Hello World, ""How are you today"" 
<a href=""www.hello.comm"">Hello</a> 
etc. 
</p> 

正如你所看到的,一些內容被包裹有兩對雙引號的。

我期望的結果是一對,以取代兩對雙引號:

<p> Hello World, "How are you today" 
<a href="www.hello.comm">Hello</a> 
etc. 
</p> 

我曾嘗試是:

page_content.gsub!(/[""]/, '"') 
page_content.gsub!("\"\"", '"') 

這似乎並沒有做的工作。關於如何獲得我想要的結果的任何建議?

回答

3

瞭解像引入nokogiri分析器是如何工作是很重要的。

爲了幫助你,它試圖修復損壞/格式錯誤的HTML或XML。你的HTML格式不正確,所以Nokogiri會解析它,但是,這個過程會讓Nokogiri進一步破壞HTML。爲避免這種情況,我們有時必須在將內容交給Nokogiri之前對其進行預處理,否則我們必須通過替換節點來解開它。

require 'nokogiri' 

doc = Nokogiri::HTML(<<EOT) 
<p> Hello World, ""How are you today"" 
<a href=""www.hello.comm"">Hello</a> 
etc. 
</p> 
EOT 

將HTML解析爲DOM。

doc.at('p').to_html 
# => "<p> Hello World, \"\"How are you today\"\"\n<a href=\"\" www.hello.comm>Hello</a>\netc.\n</p>" 

文本""How are you today""未經任何忙玲處理,因爲它是一個文本節點:

doc.at('p').child.class # => Nokogiri::XML::Text 
doc.at('p').child.content # => " Hello World, \"\"How are you today\"\"\n" 

這是很容易固定解析後:

doc.at('p').child.content = doc.at('p').child.content.gsub('""', '"') 
# => " Hello World, \"How are you today\"\n" 

試圖修復<a>標籤的參數是一個完全不同的故事,因爲在那一點上,Nokogiri已經修復了雙引號,導致標記錯誤:

doc.at('a').to_html 
# => "<a href=\"\" www.hello.comm>Hello</a>" 

請注意,www.hello.comm已在其包含引號之外進行推廣。

爲了解決這個問題,需要一些預處理,然後將交給Nokogiri,或者修復節點並用固定節點替換損壞的節點。

下面是預處理<a>標籤的基礎:

html = <<EOT 
<p> Hello World, ""How are you today"" 
<a href=""www.hello.comm"">Hello</a> 
etc. 
</p> 
EOT 

html.gsub(/href=""([^"]+)""/, 'href="\1"') 
# => "<p> Hello World, \"\"How are you today\"\"\n<a href=\"www.hello.comm\">Hello</a>\netc.\n</p>\n" 

如果你走這條路,不要花哨。編寫小的原子更改,以避免在HTML更改時出現模式中斷。

更健壯的方式(其中,「穩健」是略小於我們通常開始使用分析器)是:

bad_a = doc.at('a') 
fixed_a = bad_a.to_html.gsub(/""\s([^>]+)>/, '"\1">') 
bad_a.replace(fixed_a) 
doc.at('p') 
# => #(Element:0x3fe4ce9de9e4 { 
#  name = "p", 
#  children = [ 
#  #(Text " Hello World, \"How are you today\"\n"), 
#  #(Element:0x3fe4ce9e0fdc { 
#   name = "a", 
#   attributes = [ 
#   #(Attr:0x3fe4ce9e0fa0 { 
#    name = "href", 
#    value = "www.hello.comm" 
#    })], 
#   children = [ #(Text "Hello")] 
#   }), 
#  #(Text "\netc.\n")] 
#  }) 

doc.at('p').to_html 
# => "<p> Hello World, \"How are you today\"\n<a href=\"www.hello.comm\">Hello</a>\netc.\n</p>" 

它可以使用毯子gsub按摩文字,但是這有在大型/複雜文件中造成附帶損害的高風險。想象一下,當有含空字符串像許多標籤會發生什麼樣的文件,如果使用

html.gsub('""', '"') 

<input value="" name="foo"><input value="" name="bar"> 

搜索結果/替換將是:

<input value=" name="foo"><input value=" name="bar"> 

這幾乎不能改善事情,反而會讓文件更加糟糕。

相反,最好通過手術解決問題。回到網絡黑暗,早期和開拓者的日子,我們曾經看到大量畸形的內容,並且必須使用正則表達式處理它纔是正常的攻擊計劃。現在,通過解析器,我們通常可以避免它,並可以隔離問題並有選擇地修復我們想要的內容。看看這樣做的代碼表明,做正確的事情並不需要很多。

0
page_content.gsub!('\"\"', '"') 
+0

除了一個非常簡單的例子,這在任何HTML文檔中都是一個非常糟糕的主意。 「'? –

相關問題