Как создать другой формат HTML из коллекции Nokogiri в Ruby - PullRequest
0 голосов
/ 07 мая 2019

Я работаю над сценарием, который переносит текущую страницу HTML и преобразует ее в другой макет HTML.Я могу получить информацию из документа, используя Nokogiri и XPath.

Проблема заключается в том, как обойти узлы, извлеченные с помощью цикла, аналогично тому, как массив и хеш обходятся, чтобы создать макет, который яneed.

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

<ul id="nav">
    <li><a href="somelink1.html">Link 1</a> </li>
    <li>
        <a href="#">Link 2</a>
        <ul>
            <li><a href="sublink1.html">Sublink 1</a></li>
            <li><a href="sublink2.html">Sublink 2</a></li>
        </ul>
    </li>
</ul>

Этот код - то, что я пробовал до сих пор.Проблема в том, что когда он проходит по набору набора, он выводит все узлы в новом HTML-теге каждый раз, когда выполняется проход через коллекцию, а не только выводит информацию по текущему индексу.

require 'nokogiri'
source_file = Nokogiri.XML(open("navigation.inc"))
source_file = Nokogiri.XML(source_file.to_s.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: ''))

navigation = ""

if source_file.xpath("//ul[@id = 'nav']").length > 0

   navcontain = source_file.xpath("//ul[@id = 'nav']/li")

   navcontain.each do | child |

   if child.xpath("//li and count(*) = 2")
        navigation = navigation + "<details>"
        child.xpath("//li/ul").each do | children |
                 navigation = navigation + child.xpath("//li/a").to_s

         end #end child loop
        navigation = navigation + "</details>"
     else
        navigation = navigation + source_file.xpath("//ul[@id = 'nav']/li/a").to_s

     end #end conditional check
   end #end initial loop
end #end length check

puts navigation

Это пример того, что код выше делает в настоящее время:

<div id="nav">
    <details>
        <a href="somelink1.html">Link 1</a>
        <a href="#">Link 2</a>
        <a href="sublink1.html">Sublink 1</a>
        <a href="sublink2.html">Sublink 2</a>
    </details>
    <details>
        <a href="somelink1.html">Link 1</a>
        <a href="#">Link 2</a>
        <a href="sublink1.html">Sublink 1</a>
        <a href="sublink2.html">Sublink 2</a>
    </details>

</div>

Формат, который я хочу после преобразования:

<div id="nav">
    <a href="somelink1.html">Link 1</a>

    <details>
        <summary>
            Link 2
        </summary>

        <a href="sublink1.html">Sublink 1</a>
        <a href="sublink2.html">Sublink 2</a>

    </details>

</div>

Я считаю, что часть кода работает правильно какЯ могу определить общее количество структур ссылок одного и второго уровня.Я не понял, как перевести данные в нужную мне окончательную версию.

1 Ответ

0 голосов
/ 08 мая 2019

Код, который вы разместили, не производит вывод, который вы опубликовали.Код фактически производит это:

<a href="somelink1.html">Link 1</a>
<a href="#">Link 2</a>
<details>
  <a href="somelink1.html">Link 1</a>
  <a href="#">Link 2</a>
  <a href="sublink1.html">Sublink 1</a>
  <a href="sublink2.html">Sublink 2</a>
</details>

Я думаю, вы не хотите Link 1 и Link 2 в разделе <details>.

Существует проблема с тем, как вы используетеСелекторы XPath:

child.xpath("//li/ul")

поиск начинается с корня документа, а не с элемента child.Вместо этого вам нужно использовать:

child.xpath(".//li/ul")

, если вы хотите искать, начиная с элемента child.

Вот очищенный код, который должен выдать вам нужный вывод:

require 'nokogiri'
source_file = Nokogiri.XML(File.read("navigation.inc").encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: ''))

navigation = ""

if source_file.xpath("//ul[@id = 'nav']").length > 0
  navcontain = source_file.xpath("//ul[@id = 'nav']/li")

  navcontain.each do |child|
    if child.xpath(".//li and count(*) = 2")
      navigation += "<details>"

      child.xpath(".//ul/li/a").each do |grandchild|
        navigation += grandchild.to_s
      end

      navigation = navigation + "</details>"
    else
      # not sure how that's supposed to work based on your input file example
       navigation = navigation + source_file.xpath("//ul[@id = 'nav']/li/a").to_s
    end
  end
end

puts navigation
...