#ruby #xml #nokogiri
#ruby #xml #nokogiri
Вопрос:
require 'nokogiri'
doc = Nokogiri::XML "<root>
<a>foo<c>bar</c></a>
<b>jim<d>jam></d></b>
<a>more</a>
<x>no no no</x>
</root>"
doc.css("a, b").each {|o| p o.to_s}
# "<a>foo<c>bar</c></a>"
# "<a>more</a>"
# "<b>jim<d>jamamp;></d></b>"
Как я могу сохранить теги в их первоначальном порядке? Или также удалить вложенные теги?
Ответ №1:
Возможно, вы захотите посмотреть на белый список / blacklist / scrubbing gems. На ум приходят дезинфекция и мочалка.
Из описания Sanitize:
Учитывая список допустимых элементов и атрибутов, Sanitize удалит весь неприемлемый HTML из строки.
Из описания люфы:
Loofah превосходно очищает HTML (предотвращение XSS). Он включает в себя несколько хороших средств очистки HTML, которые основаны на белом списке HTML5lib, поэтому, скорее всего, это не сделает ваши коды менее безопасными. (Эти инструкции не были оценены Netexperts.)
В любом случае, они избавят вас от необходимости изобретать велосипед.
Ответ №2:
require 'nokogiri'
doc = Nokogiri::XML "
<root>
<a>foo<c>bar</c></a>
<b>jim<d>jam></d></b>
<a>more</a>
<x>no no no</x>
</root>"
doc.xpath('root//*[name()!="a"][name()!="b"]').remove
puts doc
#=> <?xml version="1.0"?>
#=> <root>
#=> <a>foo</a>
#=> <b>jim</b>
#=> <a>more</a>
#=>
#=> </root>
Ответ №3:
Если это просто проблема порядка, и ни один из тегов, которые вам нужно изолировать, не является вложенным, использование XPath вместо CSS-селекторов в Nokogiri должно возвращать теги в том же порядке, в котором они находятся в документе:
doc.xpath("//a | //h3").each { |o| puts o }
Я не уверен, что такое поведение предусмотрено какой-либо спецификацией для Nokogiri, поэтому вы можете быть осторожны, но по моему опыту это правда.
Конечно, если нужные вам теги когда-либо являются вложенными, вам может потребоваться определить, что означает «удалить все теги, кроме определенных» (например, что происходит с удаленными тегами и их содержимым, которые существуют внутри не удаленных тегов и их содержимого и т.д.).
Если ваше требование достаточно сложное, так что запросы XPath не будут его выполнять, вам может потребоваться «обойти DOM», используя что-то вроде doc.root.children
и рекурсивно проверить дочерние элементы каждого узла.