Как применить дополнительный встроенный стиль к html-тегам в ruby?

У меня есть строка html. В этой строке я хочу проанализировать все теги <p> и применить дополнительный встроенный стиль.

Дополнительный стиль: style="margin:0px;padding:0px;" или что-то другое

Случай 1:

входная строка: <p>some string</p>

выходная строка: <p style="margin:0px;padding:0px;">some string</p>

Случай 2:

входная строка: <p style="text-align:right;" >some string</p>

выходная строка: <p style="text-align:right;margin:0px;padding:0px;">some string</p>

Случай 3:

входная строка: <p align="justify">some string</p>

выходная строка: <p style="margin:0px;padding:0px;" align="justify">some string</p>

Прямо сейчас я использую регулярное выражение, подобное этому

myHtmlString.gsub("<p", "<p style = \"margin:0px;padding:0px\"")

Что отлично работает, за исключением того, что он удаляет предыдущий стиль. Я использую Руби (ROR).

Мне нужна помощь, чтобы настроить это немного.


person ʞɹᴉʞ ǝʌɐp    schedule 01.07.2013    source источник
comment
html не может быть проанализирован регулярным выражением. почему бы не использовать парсер xml?   -  person user428517    schedule 01.07.2013
comment
Его может анализировать регулярное выражение. Вы просто не хотите этого делать по причинам здесь   -  person hd1    schedule 01.07.2013
comment
@hd1 некоторые базовые предсказуемые строки html могут быть проанализированы регулярным выражением (в конце концов, вы можете попытаться проанализировать любую строку текста с помощью регулярного выражения), но html не является обычным языком, поэтому произвольный html не может быть проанализирован регулярным выражением   -  person user428517    schedule 01.07.2013
comment
Если вы прочитаете ссылку, которую я дал, @sgroves, она в значительной степени говорит о том, что вы написали.   -  person hd1    schedule 01.07.2013
comment
@hd1 круто. тогда мы согласны.   -  person user428517    schedule 01.07.2013


Ответы (3)


Вы можете сделать это с помощью Nokogiri, установив [:style] на соответствующих узлах.

require "nokogiri"

inputs = [
  '<p>some string</p>',
  '<p style="text-align:right;" >some string</p>',
  '<p align="justify">some string</p>'
]

inputs.each do |input|
  noko = Nokogiri::HTML::fragment(input)
  noko.css("p").each do |tag|
    tag[:style] = (tag[:style] || "") + "margin:0px;padding:0px;"
  end
  puts noko.to_html
end

Это будет перебирать все элементы, соответствующие селектору css p, и устанавливать атрибут style, как вы хотите.

Выход:

<p style="margin:0px;padding:0px;">some string</p>
<p style="text-align:right;margin:0px;padding:0px;">some string</p>
<p align="justify" style="margin:0px;padding:0px;">some string</p>
person Dogbert    schedule 01.07.2013

Я рекомендую не использовать для этого регулярное выражение, так как обычно HTML не может быть правильно проанализирован регулярным выражением. Тем не менее, пока ваши входные данные согласуются, регулярное выражение все равно будет работать. Вы хотите сопоставить любой контент, который уже находится в атрибуте style элемента p, используя круглые скобки, а затем вставить его в строку подстановки:

myHtmlString.gsub(/<p( style="(.*)")?/,
                  "<p style=\"#{$2};margin:0px;padding:0px\"")

Вот как работает шаблон соответствия:

/        #regex delimiter
<p       #match start of p tag
(        #open paren used to group, everything in this group gets saved in $1
 style=" #open style attribute
(.*)     #group contents of style attribute, gets saved to $2
"        #close style attribute
)?       #question mark makes everything in the paren group optional
/        #regex delimiter
person user428517    schedule 01.07.2013
comment
Это не касается случая 3 выше. - person ʞɹᴉʞ ǝʌɐp; 01.07.2013
comment
@deepak это не так? я не проверял это, но я не понимаю, почему это не так. это регулярное выражение не ищет атрибуты, кроме style, поэтому оно будет вставлять новый атрибут style перед любыми другими атрибутами тега p. он не удалит какие-либо существующие атрибуты. - person user428517; 01.07.2013

Я закончил тем, что сделал что-то вроде этого, я должен был сделать это непосредственно перед отправкой электронного письма. Я знаю, что это не лучший способ сделать это, но стоит поделиться здесь. Решения, предоставленные @sgroves и @Dobert, действительно хороши и полезны.

Но я не хочу включать Nokogiri, хотя я выбрал идею только из двух решений. Спасибо.

Вот мой код (я новичок в ROR, поэтому здесь нет ничего особенного, я использовал его в блоке HAML)

 myString.gsub!(/<p[^>]*>/) do |match|
   match1 = match
   style1_arr = match1.scan(/style=".*"/)
   unless style1_arr.blank?
     style1 = style1_arr.first.sub("style=", "").gsub(/\"/, "").to_s
     style2 = style1 + "margin:0px;padding:0px;"
     match2 = match1.sub(/style=".*"/, "style=\"#{style2.to_s}\"")
   else
     match2 = match1.sub(/<p/, "<p style = \"margin:0px;padding:0px;\"")
   end
 end

Теперь myString будет обновлена ​​строка (обратите внимание на ! после gsub)

person ʞɹᴉʞ ǝʌɐp    schedule 05.07.2013