2017-05-05 28 views
0

我正在使用HTTParty從第三方獲取XML文檔。 HTTParty使用MultiXML,默認情況下使用Nokogiri將返回的文檔解析爲一組Ruby對象。 XML文檔中的一些節點應該是「1或更多」或「0或更多」元素(又名序列)的數組,但是當它們僅包含單個元素時,它們僅作爲父元素的值返回,而不是數組中的單個項目。託管這些XML文件的一方還爲文檔提供了一個XSD,其中包含有關哪些節點應該是序列的信息。我知道Nokogiri有一個Schema實用程序用於根據XSD驗證文檔,但是有沒有一種方法可以使用模式向文檔解析器提供類型提示,以便這些數組節點在返回的Ruby集合中正確表示?使用XSD將XML文檔解析爲Ruby集合以提示類型

例如,給定以下簡略XML文檔:

xml_doc = <<EOT 
<Get_Workers_Response> 
    <Response_Data> 
    <Worker> 
     <Personal_Data> 
     <Contact_Data> 
      <Address_Data> 
      <Address_Line_Data>123 A Street</Address_Line_Data> 
      </Address_Data> 
     </Contact_Data> 
     </Personal_Data> 
    </Worker> 
    </Response_Data> 
</Get_Workers_Response> 
EOT 

的引入nokogiri解析器輸出:

MultiXml.parser # => MultiXml::Parsers::Nokogiri 
pp MultiXml.parse xml_doc 
{"Get_Workers_Response"=> 
    {"Response_Data"=> 
    {"Worker"=> 
     {"Personal_Data"=> 
     {"Contact_Data"=> 
      {"Address_Data"=>{"Address_Line_Data"=>"123 A Street"}}}}}}} 

當根據模式應該是:

{"Get_Workers_Response"=> 
    {"Response_Data"=> 
    {"Worker"=> # An array of worker data 
     [{"Personal_Data"=> 
     {"Contact_Data"=> # An array of Address line data 
      {"Address_Data"=>{"Address_Line_Data"=>["123 A Street"]}}}}]}}} 

我沒有被MultiXML/Nokogiri困住,所以如果有一個更好的解析器用於這種情況,我可以給予它是一個嘗試。

+0

請閱讀「[mcve]」。你給我們的數據,但沒有告訴我們你如何得到Nokogiri的輸出,這對於這個問題是至關重要的。 MultiXML允許使用多個不同的XML解析器。 Nokogiri不會返回一個Hash,所以其他事物正在處理數據;可能是MultiXML,或者它使用Ox,它返回一個Hash。使用Nokogiri本身的處理非常簡單,除了YMMV之外,我不會打擾其他任何東西。 –

+0

我已經將示例更新爲我用來測試的確切ruby。 MultiXML確實使用Nokogiri作爲解析器。 –

回答

0

你的問題沒有得到很好的解答,但它聽起來像你可能不能正確解析數據。它可以始終獲得一個或多個節點作爲陣列的內容,所以你只需要擔心處理數組:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<xml> 
<Get_Workers_Response> 
    <Address_Line_Data>123 A Street</Address_Line_Data> 
</Get_Workers_Response> 
</xml> 
EOT 

ald = doc.search('Address_Line_Data').map(&:text) # => ["123 A Street"] 

ald是在這一點上文本的數組。

如果有兩個記錄,假設他們是這樣的:

doc = Nokogiri::XML(<<EOT) 
<xml> 
<Get_Workers_Response> 
    <Address_Line_Data>123 A Street</Address_Line_Data> 
    <Address_Line_Data>456 A Street</Address_Line_Data> 
</Get_Workers_Response> 
</xml> 
EOT 

ald = doc.search('Address_Line_Data').map(&:text) # => ["123 A Street", "456 A Street"] 

ald仍然是一個字符串數組。