Как удалить недопустимые символы из XML-файла в HTTParty? - PullRequest
1 голос
/ 27 января 2012

Я пытался загрузить XML-файл с символами '&', используя гем HTTParty, и получаю эту ошибку:

"treeparser.rb:95:in `rescue in parse' <RuntimeError: Illegal character '&' 
 in raw string  "4860 BOOMM 10x20 MD&"> (MultiXml::ParseError)"

Вот мой код:

class SAPOrders
  include HTTParty
  default_params :output => 'xml'
  format :xml
  base_uri '<webservice url>'
end

xml =  SAPOrders.get('/<nameOfFile.xml>').inspect

Чего мне не хватает?

1 Ответ

3 голосов
/ 27 января 2012

Если вы используете HTTPParty и он пытается проанализировать входящий XML, прежде чем вы сможете его получить, вам нужно будет разделить этот процесс на get и анализ, чтобы вы могли поместить код между двумя .

Я использую OpenURI и Nokogiri именно по этим причинам, но независимо от того, используете ли вы эти два или их эквиваленты, у вас будет возможность предварительно обработать XML перед его синтаксическим анализом. «&» - это недопустимый символ в голом виде; Он должен быть закодирован или находиться в блоке CDATA, но, к сожалению, в просторах Интернета существует множество искаженных каналов и файлов XML.

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

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<a>
  <b parm="4860 BOOMM 10x20 MD&">foobar</b>
</a>
EOT

puts doc.errors
puts doc.to_xml

Который выдаст:

xmlParseEntityRef: no name
<?xml version="1.0"?>
<a>
  <b parm="4860 BOOMM 10x20 MD">foobar</b>
</a>

Обратите внимание, что Нокогири лишил &, но я все еще смог получить полезный вывод. Вы должны решить, хотите ли вы ошибку и прервать ее, используя опцию STRICT, или продолжить, но Nokogiri может сделать и то, и другое, в зависимости от ваших потребностей.

Вы можете помассировать входящий XML:

require 'nokogiri'

xml = <<EOT
<a>
  <b parm="4860 BOOMM 10x20 MD&">foobar</b>
</a>
EOT

xml['MD&'] = 'MD&amp;'

doc = Nokogiri::XML(xml) do |config|
  config.strict
end

puts doc.errors
puts doc.to_xml

Который сейчас выводит:

<?xml version="1.0"?>
<a>
  <b parm="4860 BOOMM 10x20 MD&amp;">foobar</b>
</a>

Я знаю, что это не идеальный ответ, но из моего опыта, связанного с большим количеством парсинга RSS / Atom и XML / HTML, иногда нам приходится открывать пакет с грязными трюками и идти с любыми работами вместо того, что было элегантный.

Другой путь к нирване в HTTParty - это подкласс парсера . Вы должны быть в состоянии проникнуть внутрь этого потока XML к парсеру и скопировать его туда. Из документов:

# Intercept the parsing for all formats
class SimpleParser < HTTParty::Parser
  def parse
    perform_parsing
  end
end
...