如何使用Ruby的REXML验证XML中的特定属性?

时间:2010-11-22 16:36:16

标签: ruby xml automated-tests jruby rexml

我正在尝试读取我从Web服务检索到的一些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>

这是我到目前为止在Ruby中使用REXML的代码:

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

当我运行此代码时,我收到一个错误:'for line on 21

的'undefined method'

1 个答案:

答案 0 :(得分:2)

您是否与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. 日期值的格式通常不明确。对于一年中的许多天来说,很难判断它是mm / dd / yyyy还是dd / mm / yyyy。在美国,我们假设它是第一个,但欧洲是第二个。 DateTime解析器试图找出它但经常弄错,特别是当它认为它应该处理一个月22时。所以,我告诉它使用mm / dd / yyyy格式而不是让它猜测。如果日期与该格式不匹配,或者日期的值超出范围,Ruby将引发异常,因此您需要为此编写代码。
  3. 这是一个如何动态检索和解析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>