2013-05-29 1 views
1

Мы пытаемся перейти от довольно небольшой системы отслеживания ошибок к Redmine. Для нашей старой системы нет готового скрипта для решения миграции, поэтому мы хотим сделать это сами.Как заменить теги, определяющие узел?

Я предложил использовать Nokogiri для перемещения некоторых форматов в новый формат (Textile), однако у меня возникли проблемы.

Это из поля БД в БД нашей старой системы:

<ul> 
    <li>list item 1</li> 
    <li>list item 2</li> 
</ul> 

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

* list item 1 
* list item 2 

Теперь, начиная с разбора используя Nokogiri, я здесь:

def self.handle_ul(page) 
     uls = page.css("ul") 
     uls.each {|ul| 
       lis = ul.css("li") 
       lis.each { |li| 
         li.inner_html = "*" << li.text << "\n" 
       } 
     } 
end 

Это работает как шарм. Тем не менее, мне нужно сделать две замены:

<li> 
</li> 

теги должны быть удалены из <li> объекта, а также:

<ul> 
</ul> 

теги должны быть удалены из <ul> объекта. Однако я не могу найти фактические теги в объекте, представляющем его. inner_html вернулся только HTML между тегами Я ищу:

ul.inner_html 

Результаты в:

<li>list item 1</li> 
<li>list item 2</li> 

Где я могу найти теги мне нужно заменить? Я думал об использовании parent и перезаписывал дочерние теги <li> с parent.parent, но это заказывало бы их в конце бабушки и дедушки.

Могу ли я каким-либо образом получить доступ ко всему HTML-представлению объекта, не удаляя его определяющие теги, чтобы я мог их заменить?


EDIT:

В соответствии с просьбой, вот макет старой записи БД и стиль он должен иметь в текстильной.

Перед преобразованием:

Fixed for rev. 1.7.92. 

<h4>Problems:</h4> 
<ul> 
<li>fixed.</li> 
<li>fixed. New minimum 270x270</li> 
<li>fixed.</li> 
<li>fixed.</li> 
<li>fixed.</li> 
<li>fixed. Column types list is growing horizontally now.</li> 
</ul> 

После трансформации:

Fixed for rev. 1.7.92. 

h4.Problems: 
* fixed. 
* fixed. New minimum 270x270 
* fixed. 
* fixed. 
* fixed. 
* fixed. Column types list is growing horizontally now. 

EDIT 2:

Я пытался переписать части из to_s метода элементов Nokogiri:

li.to_s["<li>"]="" 

, но это, похоже, не является допустимым значением lvalue (не то, что есть ошибка, он просто ничего не делает).

+0

Зачем нужна замена тега *, скорее, вы можете напрямую извлечь текст, верно? Я ничего не понял? –

+0

Мне нужно сохранить документ в целом, только меняя определенные структуры тегов. Если бы я извлек текст, мне нужно было бы знать, где он находится в целевом документе, информация, которая будет потеряна. – 0xCAFEBABE

+0

, поэтому вы хотите реструктурировать существующий документ с удалением тегов 'li' и' ul'. Можете ли вы показать нам вывод более явным образом? после замены того, что будет в результате html? –

ответ

1

Вот основа для такого преобразования:

require 'nokogiri' 

doc = Nokogiri::HTML(<<EOT) 
<ul> 
    <li>list item 1</li> 
    <li>list item 2</li> 
</ul> 
EOT 
puts doc.to_html 

doc.search('ul').each do |ul| 
    ul.search('li').each do |li| 
    li.replace("* #{ li.text.strip }") 
    end 
    ul.replace(ul.text) 
end 

puts doc.to_html 

Запуск, что выходы:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
<html><body><ul> 
<li>list item 1</li> 
    <li>list item 2</li> 
</ul></body></html> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
<html><body>* list item 1 
    * list item 2 
</body></html> 

Я не хотел, или попытка, чтобы сделать первый «элемент» имеет ведущую каретку - возврат или подача строки. Это остается как упражнение для читателя. Я также не пытался обрабатывать теги <h4> или аналогичные подстановки. Из кода ответа вы должны выяснить, как это сделать.

Кроме того, я использую Nokogiri::HTML для разбора HTML, который превращает его в полноценный HTML-документ с соответствующим заголовком DOCTYPE, <html> и <body> тегов, чтобы имитировать полный HTML документ. Это можно было бы изменить с помощью Nokogiri::HTML::DocumentFragment.parse, но на самом деле не повлияло бы на результат.

+0

Спасибо, это очень полезно. – 0xCAFEBABE

+0

@ 0xCAFEBABE Если вы сделаете это, подумайте о выпуске драгоценного камня! –

1

Возможно, вы захотите посмотреть на ClothRed, который является конвертером HTML to Textile в Ruby. Он не обновлялся через некоторое время, но он прост и может быть хорошей отправной точкой для вашего собственного конвертера.

Если вы действительно хотите использовать Nokogiri, вы пишете фильтр, поэтому вы можете использовать интерфейс SAX.

+0

Я посмотрю, может быть, это спасет нас от неприятностей. Благодарю. +1 – 0xCAFEBABE

+0

Не похоже, что это «конвертер». Там не происходит синтаксический анализ, он прямо заменяет HTML-теги текстильными тегами. К сожалению, вряд ли какой-либо HTML сейчас легко. – 0xCAFEBABE

+0

Зависит от того, что вы пытаетесь преобразовать. Если это результат текстового редактора с поддержкой javascript в браузере, он может быть достаточно последовательным для этого. Если это произвольный HTML, тогда вам лучше решать синтаксический анализ, например ответ Tin Man. –

1

Возможно, вы захотите попробовать McBean (https://github.com/flavorjones/mcbean) [caveat: Я автор драгоценного камня, и он не обновлялся некоторое время].

Он похож на ClothRed по духу, но использует Nokogiri под капотом и фактически преобразует структуру документа в выходной текст. Он поддерживает существенное подмножество Textile; и на самом деле я успешно использовал его для преобразования страниц wiki между вики-системами, которые вы пытаетесь сделать.

+0

Я посмотрю, спасибо. – 0xCAFEBABE

0

Если кто-нибудь заинтересован в этом позже, другой альтернативой является использование Pandoc. Я только что сделал свои первые тесты, и это кажется почти достаточным, и он может делать гораздо больше форматов.