Подтвердить что ты не робот

Анализ простого XML с помощью Nokogiri

У меня есть следующий XML:

<links>

  <item>
    <title>Title 1</title>
    <url>http://www.example.com/url-1</url>
  </item>

  <item>
   <title>Title 2</title>
   <url>http://www.example.com/url-2</url>
  </item>

  <item>
    <title>Title 3</title>
    <url>http://www.example.com/url-3</url>
  </item>

</links>

И я хотел бы преобразовать его в список HTML:

<ul>
  <li><a href="#" onclick="location.href='http://www.example.com/url-1'; return false;">Title 1</a></li>
  <li><a href="#" onclick="location.href='http://www.example.com/url-2'; return false;">Title 2</a></li>
  <li><a href="#" onclick="location.href='http://www.example.com/url-3'; return false;">Title 3</a></li>
</ul>

В настоящее время у меня есть это:

Контроллер:

require 'nokogiri'
doc = Nokogiri::XML(...)

@links = doc.xpath('//links/item').map do |i|
  {'title' => i.xpath('//title'), 'url' => i.xpath('//url')}
end

Шаблон:

<ul>
  <% @links.each do |l| %>
    <li><a href="<%= l['url'] %>"><%= l['title'] %></a></li>
  <% end %>
</ul> 

Результат HTML:

<ul>
  <li><a href="#" onclick="location.href='http://www.example.com/url-1http://www.example.com/url-2http://www.example.com/url-3'; return false;">Title 1Title 2Title 3</a></li>
  <li><a href="#" onclick="location.href='http://www.example.com/url-1http://www.example.com/url-2http://www.example.com/url-3'; return false;">Title 1Title 2Title 3</a></li>
  <li><a href="#" onclick="location.href='http://www.example.com/url-1http://www.example.com/url-2http://www.example.com/url-3'; return false;">Title 1Title 2Title 3</a></li>
</ul>

Что я делаю неправильно? Есть ли более оптимальный способ сделать это?

4b9b3361

Ответ 1

Заменить это:

@links = doc.xpath('//links/item').map do |i| 
  {'title' => i.xpath('//title'), 'url' => i.xpath('//url')} 

с

@links = doc.xpath('//links/item').map do |i| 
  {'title' => i.xpath('title'), 'url' => i.xpath('url')} 

Объяснение

//title 

и

//url

являются абсолютными выражениями XPath, и они выбирают все (соответственно) title и все элементы url в документе XML.

Контрастируйте это с помощью:

title

и

url

Это относительные выражения XPath и выберите все (соответственно) title и url только для детей текущего node.

Ответ 2

Проблема заключается в том, что Xpath //title выполняет поиск заголовков из корня документа и возвращает все теги title. Использование поиска Xpath title в контексте данного node, как вы хотите. Тоже на url.

@links = doc.xpath('//links/item').map do |i|
  {'title' => i.xpath('title'), 'url' => i.xpath('url')}
end