2010-11-22 100 views
0

我正在嘗試讀取從Web服務檢索到的一些XML,並驗證XML中的特定屬性。如何使用Ruby的REXML驗證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 

當我運行這段代碼我得到一個錯誤:「未定義的方法‘在’爲#第21行

回答

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 

有幾件事情怎麼回事,可以使這個harde r來處理比簡單的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> 
+0

這真棒,但我有一個問題。 XML是動態的,因爲每次我點擊Web服務時,都會有一個新的時間/日期戳記。我需要Nokogiri從內存中讀取xml。所以我採取了我的薩貢請求,並做到了這一點: xml = request.to_s() – r3nrut 2010-11-22 18:20:29