ruby-on-rails - 解析 'ul' 和 'ol' 标签

标签 ruby-on-rails ruby algorithm ruby-on-rails-4 nokogiri

我必须处理 ulolli 标签的深层嵌套。我需要提供与我们在浏览器中提供的 View 相同的 View 。我想在pdf文件中实现以下示例:

 text = "
<body>
    <ol>
        <li>One</li>
        <li>Two

            <ol>
                <li>Inner One</li>
                <li>inner Two

                    <ul>
                        <li>hey

                            <ol>
                                <li>hiiiiiiiii</li>
                                <li>why</li>
                                <li>hiiiiiiiii</li>
                            </ol>
                        </li>
                        <li>aniket </li>
                    </li>
                </ul>
                <li>sup </li>
                <li>there </li>
            </ol>
            <li>hey </li>
            <li>Three</li>
        </li>
    </ol>
    <ol>
        <li>Introduction</li>
        <ol>
            <li>Introduction</li>
        </ol>
        <li>Description</li>
        <li>Observation</li>
        <li>Results</li>
        <li>Summary</li>
    </ol>
    <ul>
        <li>Introduction</li>
        <li>Description

            <ul>
                <li>Observation

                    <ul>
                        <li>Results

                            <ul>
                                <li>Summary</li>
                            </ul>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
        <li>Overview</li>
    </ul>
</body>"

我必须用虾来完成我的任务。但是大虾不支持HTML标签。所以,我想出了一个使用 nokogiri 的解决方案:我正在解析并稍后删除带有 gsub 的标签。我为上述内容的一部分编写了以下解决方案,但问题是 ul 和 ol 可能会有所不同。

     RULES = {
  ol: {
    1 => ->(index) { "#{index + 1}. " },
    2 => ->(index) { "#{}" },
    3 => ->(index) { "#{}" },
    4 => ->(index) { "#{}" }
  },
  ul: {
    1 => ->(_) { "\u2022 " },
    2 => ->(_) { "" },
    3 => ->(_) { "" },
    4 => ->(_) { "" },
  }
}

def ol_rule(group, deepness: 1)
  group.search('> li').each_with_index do |item, i|
    prefix = RULES[:ol][deepness].call(i)
    item.prepend_child(prefix)
    descend(item, deepness + 1)
  end
end

def ul_rule(group, deepness: 1)
  group.search('> li').each_with_index do |item, i|
    prefix = RULES[:ul][deepness].call(i)
    item.prepend_child(prefix)
    descend(item, deepness + 1)
  end
end

def descend(item, deepness)
  item.search('> ol').each do |ol|
    ol_rule(ol, deepness: deepness)
  end
  item.search('> ul').each do |ul|
    ul_rule(ul, deepness: deepness)
  end
end

doc = Nokogiri::HTML.fragment(text)

doc.search('ol').each do |group|
  ol_rule(group, deepness: 1)
end

doc.search('ul').each do |group|
  ul_rule(group, deepness: 1)
end


  puts doc.inner_text


1. One
2. Two

1. Inner One
2. inner Two

• hey

1. hiiiiiiiii
2. why
3. hiiiiiiiii


• aniket 


3. sup 
4. there 

3. hey 
4. Three



1. Introduction

1. Introduction

2. Description
3. Observation
4. Results
5. Summary



• Introduction
• Description

• Observation

• Results

• Summary






• Overview

问题

1) 我想要实现的是在使用 ul 和 ol 标签时如何处理空间
2) li come inside ul or li come inside ol 如何处理深嵌套

最佳答案

我想出了一个解决方案,可以处理多个标识,每个级别都有可配置的编号规则:

require 'nokogiri'
ROMANS = %w[i ii iii iv v vi vii viii ix]

RULES = {
  ol: {
    1 => ->(index) { "#{index + 1}. " },
    2 => ->(index) { "#{('a'..'z').to_a[index]}. " },
    3 => ->(index) { "#{ROMANS.to_a[index]}. " },
    4 => ->(index) { "#{ROMANS.to_a[index].upcase}. " }
  },
  ul: {
    1 => ->(_) { "\u2022 " },
    2 => ->(_) { "\u25E6 " },
    3 => ->(_) { "* " },
    4 => ->(_) { "- " },
  }
}

def ol_rule(group, deepness: 1)
  group.search('> li').each_with_index do |item, i|
    prefix = RULES[:ol][deepness].call(i)
    item.prepend_child(prefix)
    descend(item, deepness + 1)
  end
end

def ul_rule(group, deepness: 1)
  group.search('> li').each_with_index do |item, i|
    prefix = RULES[:ul][deepness].call(i)
    item.prepend_child(prefix)
    descend(item, deepness + 1)
  end
end

def descend(item, deepness)
  item.search('> ol').each do |ol|
    ol_rule(ol, deepness: deepness)
  end
  item.search('> ul').each do |ul|
    ul_rule(ul, deepness: deepness)
  end
end

doc = Nokogiri::HTML.fragment(text)

doc.search('ol:root').each do |group|
  binding.pry
  ol_rule(group, deepness: 1)
end

doc.search('ul:root').each do |group|
  ul_rule(group, deepness: 1)
end

然后您可以根据您的环境删除标签或使用 doc.inner_text。

但有两个注意事项:

  1. 必须仔细选择您的条目选择器。我在没有根元素的情况下逐字使用了您的代码段,因此我不得不使用 ul:root/ol:root。也许“body > ol”也适用于您的情况。也许选择每个 ol/ul,但不是遍历每个并只找到那些没有列表父级的。
  2. 逐字使用您的示例,Nokogiri 不能很好地处理第一组的最后 2 个列表项(“嘿”、“三”) 当用 nokogiri 解析时,元素已经“离开”它们的 ol 树并被放置在根树中。

当前输出:

  1. One
  2. Two
      a. Inner One
      b. inner Two
        ◦ hey
        ◦ hey
      3. hey
      4. hey
  hey
  Three

  1. Introduction
    a. Introduction
  2. Description
  3. Observation
  4. Results
  5. Summary

  • Introduction
  • Description
      ◦ Observation
          * Results
              - Summary
  • Overview

关于ruby-on-rails - 解析 'ul' 和 'ol' 标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50326433/

相关文章:

ruby-on-rails - Searchkick-具有多个模型和字段的自动完成

ruby-on-rails - ruby rails 2.3.8 : Been having trouble getting testing things to work

ruby-on-rails - RSpec 在 controller_spec 中将对象作为参数传递

ruby-on-rails - 在 ruby​​ on rails 中将参数从一个 Controller 传递到另一个 Controller

ruby - Sinatra 应用程序无法运行

mysql - rubyonrails mysql2

html - Bootstrap 媒体对象图像调整大小

java - 我的快速排序算法中的 Stackoverflow 错误

algorithm - 我应该/可以在此函数中使用 `assoc` 来重新定义函数参数吗?

c# - 反转哈希函数