Как использовать преобразователи RubyGem Sanitize для очистки неупорядоченного списка в список, разделенный запятыми? - PullRequest
0 голосов
/ 23 декабря 2011

Любой, кто знаком с RubyGem Sanitize, который предоставляет пример построения «Трансформера» для преобразования

"<ul><li>a</li><li>b</li><li>c</li></ul>" 

в

"a,b, and c"

1 Ответ

1 голос
/ 24 декабря 2011

Преобразователи IMO не предназначены для извлечения данных, таких как:

Преобразователи позволяют вам фильтровать и изменять узлы, используя собственную собственную логику [...]

Это не то, что вы пытаетесь сделать;Вы пытаетесь извлечь данные из узлов и преобразовать их.В вашем примере вы не делаете одно и то же для каждого элемента: иногда вы добавляете запятую, иногда добавляете запятую и слово «и».

Чтобы сделать это, вам нужно либочтобы сохранить состояние и последующую обработку, или заглянуть в поток узлов, чтобы увидеть, посещаете ли вы последний узел.Я не знаю тривиального способа сделать это с помощью преобразователей Sanitize, поэтому этот пример сохраняет состояние и пост-процессы.

require 'sanitize'
items = []
s = "<ul><li>some space</li><li>more stuff with spaces</li><li>last one</li></ul>"
save_li = lambda do |env|
  node = env[:node]
  items << node.text.strip if node.text?
end
Sanitize.clean(s, :transformers => save_li)
# => "  some space  more stuff with spaces  last one  "    
output = "#{items[0..-2].join(", ")}, and #{items[-1]}"
# => "some space, more stuff with spaces, and last one"

IMO этот пример - злоупотребление преобразователями, потому что он запускается только из-за его побочного эффекта, он ничего не делает, кроме как ищет текстовые узлы.

Если один из элементов списка имеет встроенный HTML, наивный подход больше не работает, и вам нужно начать знать больше Nokogiriв любом случае:

items = []
s = "<ul><li>some space</li><li>item <b>with<b/> html</li><li>c</li></ul>"
save_li = lambda do |env|
  node = env[:node]
  items << node.content if node.name == "li"
end
Sanitize.clean(s, :transformers => save_li)
# => "  some space  item with html  c  "
output = "#{items[0..-2].join(", ")}, and #{items[-1]}"    
# => "some space, item with html, and c"

Этот подход основан на стандартном поведении Sanitize, когда ничто не занесено в белый список.Теги <b> все еще посещаются лямбдой save_li, но они очищаются.Это может вызвать проблемы при различных обстоятельствах.

...