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!("\"\"", '"')

这似乎不起作用。关于如何获得我想要的结果的任何建议?

4

4 回答 4

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已在其包含的引号之外进行了提升。

要解决此问题,需要在将 HTML 交给 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">

这几乎没有改善事情,反而会进一步严重破坏文档。

相反,最好通过手术解决问题。回到黑暗的、早期的网络先驱时代,我们曾经看到大量格式不正确的内容,而必须使用正则表达式对其进行处理是正常的攻击计划。现在,有了解析器,我们通常可以避免它,并且可以隔离问题并有选择地修复我们想要的。查看执行此操作所需的代码表明,将其做好并不需要太多。

于 2013-11-20T21:04:38.430 回答
0
page_content.gsub!('\"\"', '"')
于 2013-11-14T10:58:51.360 回答
-1
page_content.gsub!(/"{2}/, '"')

rubular.com

于 2013-11-14T13:01:12.023 回答
-1
a='<p> Hello World, ""How are you today""
<a href=""www.hello.comm"">Hello</a>
etc.
</p>'

a.gsub! '""', '"'

[19] pry(main)> puts a
<p> Hello World, "How are you today"
<a href="www.hello.comm">Hello</a>
etc.
</p>
于 2013-11-14T20:35:32.687 回答