(Rails) Не могу заставить Mechanize правильно читать веб-файл XML - PullRequest
0 голосов
/ 18 февраля 2012

Я должен прочитать XML-файлы, доступные через http с аутентификацией.Вот почему я использую Mechanize.

Моя проблема в том, что я не могу заставить Mechanize распознавать эти XML-файлы, поэтому я могу использовать .find или .search для них.

Вот что я пыталсяпервое - на мой взгляд (html-файл)

<% agent = Mechanize.new %>

<% page = agent.get("http://dl.dropbox.com/u/344349/xml.xml") %>

<%= page %>

Что возвращает #<Mechanize::File:0x007f9dd602de30>.Это ::File, а не ::Page Я не могу использовать .find или .search для этого, так как это приведет к ошибке с undefined method find for #<Mechanize::File:0x007f9dd624cbd0>

Mechanize doc говорит: Это класс по умолчанию (и базовый)для сменных парсеров.Если Mechanize не может найти подходящий класс для использования в качестве типа контента, этот класс будет использоваться.Например, если вы загрузите JPG, Mechanize не будет знать, как его анализировать, поэтому будет создан экземпляр этого класса.

Итак, я создал класс, как описано здесь: http://rdoc.info/github/tenderlove/mechanize/master/Mechanize/PluggableParser

My class

class XMLParser < Mechanize::File

attr_reader :xml

def initialize(uri=nil, response=nil, body=nil, code=nil)

super(uri, response, body, code)

@xml = xml.parse(body)

end

end

и обновленный код на мой взгляд (html-файл)

<% agent = Mechanize.new %>

<% agent.pluggable_parser['text/xml'] = XMLParser %>

<% agent.user_agent_alias = 'Windows Mozilla' %>

<% page = agent.get("http://dl.dropbox.com/u/344349/xml.xml") %>

<%= page %>

или даже

<% agent = Mechanize.new %>

<% agent.pluggable_parser.xml = XMLParser %>

<% page1 = agent.get('http://dl.dropbox.com/u/344349/xml.xml') # => CSVParser %>

<%= page1 %>

Все еще возвращает #<Mechanize::File:0x007f9dd5253b48>

Я даже проверял точный код (CSVParser - http://rdoc.info/github/tenderlove/mechanize/master/Mechanize/PluggableParser) и попытался загрузить CSV-файл, который все еще рассматривается как :: File.

Что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 22 февраля 2012

Хорошо, я решил эту проблему для себя только сейчас. Решение состоит из двух частей:

Во-первых, тип контента, который вам подходит, неверен. Если вы запустите эту строку, после того как вы получите, она скажет вам, какой тип содержимого для документа, который вы получаете:

page.response['content-type'] # => 'application/xml', not 'text/xml'

Когда я использую Mechanize, чтобы получить вашу страницу ('http://dl.dropbox.com/u/344349/xml.xml'), я вижу' application / xml 'в качестве типа контента.

Во-вторых, вы неправильно используете PluggableParser. Использование XMLParser, как у вас здесь, сгенерирует NoMethodError: undefined method 'parse' for nil:NilClass. Измените определение класса, чтобы вместо него использовать Nokogiri :: XML:

class XmlParser < Mechanize::File
  attr_reader :xml
  def initialize(uri = nil, response = nil, body = nil, code = nil)
    @xml = Nokogiri::XML(body)
    super uri, response, body, code
  end
end

Затем установите это как синтаксический анализатор для правильного типа контента:

mech.pluggable_parser['application/xml'] = XmlParser

Чтобы использовать это, вы получите свою страницу такой же, как прежде, а затем будете ссылаться на атрибут xml объекта страницы как на экземпляр Nokogiri :: XML :: Document , который является подклассом Nokogiri :: XML :: Node . К счастью, Mechanize :: Page.search - это просто оболочка вокруг Nokogiri :: XML :: Node.search , так что вы можете искать практически так же, как вы ожидаете. Как это:

page.xml.search 'catalog'

Дальнейшим уточнением будет сопоставление XmlParser.search с методами Nokogiri .search:

# This is the same as what Mechanize::Page does
class XmlParser < Mechanize::File
  extend Forwardable
  def_delegators  :@xml, :search, :/, :at
end

Это позволяет выполнять поиск непосредственно на экземпляре страницы:

page.search 'catalog'
0 голосов
/ 22 ноября 2012

Вы можете изменить синтаксический анализатор на использование класса Page, например:

agent = Mechanize.new
agent.pluggable_parser.default = Mechanize::Page
agent.get("http://dl.dropbox.com/u/344349/xml.xml").class # Mechanize::Page

См. http://mechanize.rubyforge.org/Mechanize/PluggableParser.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...