如何替换定义节点的标签?

时间:2013-05-29 09:21:49

标签: ruby nokogiri textile

我们正试图从一个相当小的错误跟踪系统转移到Redmine。对于我们的旧系统,没有现成的迁移解决方案脚本,所以我们想自己做。

我建议使用Nokogiri将一些格式转换为新格式(Textile),然而,我遇到了问题。

这来自我们旧系统的DB中的DB字段:

<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表示,而不会删除其定义的标记,以便我可以替换它们吗?


编辑:

根据要求,这里是一个旧的DB条目的样本和它在纺织品中应该具有的样式。

转型前:

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>"]=""

但这似乎不是一个有效的左值(不是有错误,它只是没有做任何事情)。

4 个答案:

答案 0 :(得分:1)

您可能需要查看ClothRed,它是Ruby中的HTML to Textile转换器。它暂时没有更新,但它很简单,可能是您自己的转换器的一个很好的起点。

如果您真的想使用Nokogiri,那么您正在编写过滤器,因此您可能需要使用SAX界面。

答案 1 :(得分: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,将其转换为带有相应DOCTYPE标头<html><body>标记的完整HTML文档,以模仿完整的HTML文献。这可以使用Nokogiri::HTML::DocumentFragment.parse来改变,但不会对输出产生任何影响。

答案 2 :(得分:1)

你可能想尝试McBean(https://github.com/flavorjones/mcbean)[警告:我是宝石的作者,并且它暂时没有更新]。

它在精神上类似于ClothRed,但在引擎盖下使用Nokogiri实际上将文档结构转换为输出文本。它支持纺织品的大部分;事实上,我已经成功地使用它来在wiki系统之间转换维基页面,正如你想要的那样。

答案 3 :(得分:0)

如果有兴趣的人稍后发现,另一种选择是使用Pandoc。我刚做了第一次测试,看起来已经足够了,它可以做更多的格式。