代码之家  ›  专栏  ›  技术社区  ›  r3nrut

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

  •  0
  • r3nrut  · 技术社区  · 14 年前

    我试图读取一些从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行出现一个错误:“undefined method”at

    1 回复  |  直到 14 年前
        1
  •  2
  •   the Tin Man    14 年前

    你和雷克斯姆绑在一起了吗?或者你能换成 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>
    
    推荐文章