-3

I need to replace field_to_replace from

...<div>\r\n<span field=\"field_to_replace\">\r\n<div>....

There are multiple occurrences of field_to_replace in the string. I need to replace only this occurrence using the tag before and after it.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Rubyman
  • 874
  • 6
  • 15
  • 1
    Oh my, this question again. OK, don't use a regular expression for this as it'll be extremely fragile and likely to break, especially if you don't own the HTML generator. The only time to consider it is for _EXTREMELY_ simple HTML/XML. Instead, [use a parser](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags). The most commonly used one for Ruby is [Nokogiri](http://nokogiri.org). There are lots of examples on the internet and Stack Overflow explaining how to do this. – the Tin Man Oct 06 '15 at 18:32
  • Okay, Thanks @theTinMan – Rubyman Oct 07 '15 at 05:39

2 Answers2

1

Don't use regular expressions to try to search or replace inside HTML or XML unless you are guaranteed that the source layout won't change. It's really easy to use a parser to make the changes, and they'll easily handle changes to the source.

This would replace all occurrences of the string in the HTML:

require 'nokogiri'
doc = Nokogiri::HTML::DocumentFragment.parse("<div><span field='field_to_replace'><div>")
doc.to_html # => "<div><span field=\"field_to_replace\"><div></div></span></div>"

doc.search('div span[@field]').each do |span|
  span['field'] = 'foo'
end
doc.to_html # => "<div><span field=\"foo\"><div></div></span></div>"

If you want to replace just the first occurrence, use at instead of search:

doc = Nokogiri::HTML::DocumentFragment.parse("<div><span field=\"field_to_replace\"><div><span field='field_to_replace'></span></div></span></div>")
doc.to_html # => "<div><span field=\"field_to_replace\"><div><span field=\"field_to_replace\"></span></div></span></div>"

doc.at('div span[@field]')['field'] = 'foo'
doc.to_html # => "<div><span field=\"foo\"><div><span field=\"field_to_replace\"></span></div></span></div>"

By defining the CSS selector you can identify the node quickly and easily. And, if you need even more power then XPath can be used instead of CSS.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
0

The simple way would be:

str = "...<div>\r\n<span field=\"field_to_replace\">\r\n<span field=\"field_to_replace\">\r\n<div>...."
str.split("field_to_replace").join("new_field")

Let us know if you need something more complex.

Brian
  • 967
  • 7
  • 12
  • Agreed, str.gsub('field_to_replace', 'new_field'). Was trying to use methods more likely to be known, but your solution is better. – Brian Oct 06 '15 at 18:25