0

我正在尝试读取从 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

当我运行此代码时,我收到一个错误:“第 21 行的 # 未定义方法 'at'

4

1 回答 1

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 将引发异常,因此您需要为此编写代码。

这是一个如何动态检索和解析 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>
于 2010-11-22T17:21:17.647 回答