我们正试图从一个相当小的漏洞跟踪系统转移到Redmine。对于我们的旧系统,没有现成的迁移解决方案脚本可用,所以我们想自己做。
我建议使用Nokogiri将一些格式转移到新的格式(Textile),但是,我遇到了问题。
这是来自我们旧系统的DB中的DB字段:
<ul>
<li>list item 1</li>
<li>list item 2</li>
</ul>
这需要翻译成Textile,它看起来像这样:
* 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表示形式,而不剥离其定义标记,以便我可以替换它们?
编辑:
根据要求,这里是一个旧的数据库条目的模型,它应该在纺织品中具有风格。
之前转换:
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.
编辑2:
我试图覆盖Nokogiri元素的to_s
方法的部分:
li.to_s["<li>"]=""
,但这似乎不是一个有效的左值(不是有一个错误,它只是不做任何事情)。
下面是这样一个转换的基础:
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>
我没有打算或尝试让第一个"item"有一个前导回车或换行符。这是留给读者的练习。我也没有尝试处理<h4>
标签或类似的替换。从答案代码中,你应该能够找出怎么做。
此外,我使用Nokogiri::HTML
来解析HTML,这将其转换为具有适当DOCTYPE头,<html>
和<body>
标记的完整HTML文档,以模拟完整的HTML文档。这可以使用Nokogiri::HTML::DocumentFragment.parse
来更改,但实际上不会对输出产生影响。
您可能想看看ClothRed,它是Ruby中的HTML到Textile转换器。它有一段时间没有更新了,但它很简单,可能是你自己的转换器的一个很好的起点。
如果您真的想使用Nokogiri,那么您正在编写一个过滤器,因此您可能希望使用SAX接口。
您可能想尝试McBean (https://github.com/flavorjones/mcbean)[警告:我是gem的作者,并且它已经有一段时间没有更新了]。
它在精神上类似于ClothRed,但在底层使用Nokogiri,并实际将文档结构转换为输出文本。它支持纺织品的大量子集;事实上,我已经成功地用它在wiki系统之间转换了wiki页面,就像你想做的那样。
如果有任何感兴趣的人稍后发现这个,另一种选择是使用Pandoc。我刚刚做了第一次测试,它似乎已经足够了,而且它可以处理更多的格式。