Код на Ruby использует Nokogiri, обрабатывает HTML.
Нужно удалить лишние <div class="section">
, оставив их содержимое. Структура такая:
<div class="section" id="a">
<p>content</p>
<div class="section" id="b">
<p>content</p>
</div>
<div class="section" id="c">
<p>content</p>
</div>
<div class="section" id="d">
<p>content</p>
</div>
</div>
Пробовал два варианта:
@html.xpath("//div[@class = 'section']").each do |div|
div.parent.inner_html = div.inner_html unless div.parent.nil?
end
@html.xpath("//div[@class = 'section']").each do |div|
div.replace(div.inner_html)
end
В обоих случаях удаляется только внешний <div class="section">
, а вложенные остаются. Смотрел в логи: селектор Xpath находит все эти дивы, не только вложенный. Соответственно, и цикл проходит по всем.
Подозреваю, что после того, как заменяется первый <div>
, дерево его содержимого выстраивается заново из div.inner_html
. Поэтому остальные дивы уже находятся не в этом дереве, так что их замена ничего не даёт.
Вопрос: как заменить все?
Дополнительный вопрос: объясните, как именно происходит замена, почему вложенные дивы не заменяются?
Можно сделать внешний цикл, который будет повторять итератор @html.xpath("//div[@class = 'section']").each
до тех пор, пока он будет осуществлять хоть бы одну замену за проход. Соответственно, после каждого прохода внешнего цикла, итератор @html.xpath("//div[@class = 'section']").each
будет находить всё более вложенные элементы, пока не исчерпается вложенность.
Кроме того, можно ограничиться изменением одного элемента за один проход внешнего цикла, выполняя выход из внутреннего итератора во внешний цикл после каждой успешной замены первого найденного элемента (тем самым пересоздавая внутренний итератор на основании измененной иерархии). При таком подходе можно пойти дальше и вообще отказаться от внутреннего итератора, заменив его на вызов at_xpath
, который сразу же возвращает один найденный элемент.
Виртуальный выделенный сервер (VDS) становится отличным выбором