Как проверить определенные атрибуты в XML с помощью REXML в Ruby? - PullRequest
0 голосов
/ 22 ноября 2010

Я пытаюсь прочитать какой-то XML, полученный из веб-службы, и проверить определенный атрибут в XML.

Это XML до тега, который мне нужно проверить:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <QueryResponse xmlns="http://tempuri.org/">
      <QueryResult xmlns:a="http://schemas.datacontract.org/2004/07/Entity"
      xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:Navigation i:nil="true" />
        <a:SearchResult>
          <a:EntityList>
            <a:BaseEntity i:type="a:Product">
              <a:ExtractDateTime>1290398428</a:ExtractDateTime>
              <a:ExtractDateTimeFormatted>11/22/2010
              04:00:28</a:ExtractDateTimeFormatted>

Вот код, который я пока использую REXML в Ruby:

require 'xmlsimple'
require 'rexml/document'
require 'rexml/streamlistener'
include REXML


class Listener
include StreamListener

xmlfile = File.new("rbxml_CS_Query.xml")
xmldoc = Document.new(xmlfile)

# Now get the root element
root = xmldoc.root
puts root.attributes["a:EntityList"]

# This will output the date/time of the query response
xmldoc.elements.each("a:BaseEntity"){
   |e| puts e.attributes["a:ExtractDateTimeFormatted"]
}

end

Мне нужно проверить, что ExtractDateTimeFormatted существует и имеет допустимое значение для этого атрибута.Любая помощь очень ценится.:)


Чтение из локального XML-файла.

File.open('temp.xml', 'w') { |f|
    f.puts request
    f.close
  }

  xml = File.read('temp.xml')

  doc = Nokogiri::XML::Reader(xml)
  extract_date_time_formatted = doc.at(
    '//a:ExtractDateTimeFormatted',
    'a' => 'http://schemas.datacontract.org/2004/07/Entity'
  ).inner_text
  show = DateTime.strptime(extract_date_time_formatted, '%m/%d/%Y')
  puts show

Когда я запускаю этот код, я получаю сообщение об ошибке: «неопределенный метод» at # для строки 21

1 Ответ

2 голосов
/ 22 ноября 2010

Вы привязаны к REXML или можете переключиться на Nokogiri ? Я настоятельно рекомендую Nokogiri по сравнению с другими парсерами Ruby XML.

Мне пришлось добавить достаточное количество XML-тегов, чтобы образец был проверен.

require 'date'
require 'nokogiri'

xml = %q{<?xml version="1.0"?>
  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Body>
          <QueryResponse xmlns="http://tempuri.org/">
              <QueryResult xmlns:a="http://schemas.datacontract.org/2004/07/Entity" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                  <a:Navigation i:nil="true"/>
                  <a:SearchResult>
                      <a:EntityList>
                          <a:BaseEntity i:type="a:Product">
                              <a:ExtractDateTime>1290398428</a:ExtractDateTime>
                              <a:ExtractDateTimeFormatted>11/22/2010</a:ExtractDateTimeFormatted>
                          </a:BaseEntity>
                      </a:EntityList>
                  </a:SearchResult>
              </QueryResult>
          </QueryResponse>
      </s:Body>
  </s:Envelope>
}

doc = Nokogiri::XML(xml)

extract_date_time_formatted = doc.at(
  '//a:ExtractDateTimeFormatted', 
  'a' => 'http://schemas.datacontract.org/2004/07/Entity'
).inner_text
puts DateTime.strptime(extract_date_time_formatted, '%m/%d/%Y') 
# >> 2010-11-22T00:00:00+00:00

Происходит пара вещей, которые могут сделать это сложнее, чем простой файл XML.

  1. XML использует пространства имен. Они полезны, но вы должны указать парсеру, как с ними обращаться. Вот почему мне пришлось добавить второй параметр в аксессор at().
  2. Значение даты в формате, который часто является неоднозначным. В течение многих дней в году трудно сказать, является ли это мм / дд / гггг или дд / мм / гггг. Здесь, в США, мы предполагаем, что это первое, а Европа - второе. Синтаксический анализатор DateTime пытается выяснить это, но часто ошибается, особенно когда думает, что он должен иметь дело с месяцем 22. Поэтому, вместо того, чтобы догадываться, я сказал ему использовать формат mm / dd / yyyy. Если дата не соответствует этому формату, или значения даты выходят за пределы диапазона, Ruby выдаст исключение, поэтому вам придется кодировать это.

Это пример того, как извлекать и анализировать XML на лету:

require 'nokogiri'
require 'open-uri'

doc = Nokogiri::XML(open('http://java.sun.com/developer/earlyAccess/xml/examples/samples/book-order.xml'))
puts doc.class
puts doc.to_xml

И пример того, как прочитать локальный XML-файл и разобрать его:

require 'nokogiri'

doc = Nokogiri::XML(File.read('test.xml'))
puts doc.to_xml
# >> <?xml version="1.0"?>
# >> <root xmlns:foo="bar">
# >>   <bar xmlns:hello="world"/>
# >> </root>
...