【问题标题】:Parse XML document to Ruby collection using XSD for type hinting使用 XSD 将 XML 文档解析为 Ruby 集合以进行类型提示
【发布时间】:2017-10-04 10:57:45
【问题描述】:

我正在使用 HTTParty 从第三方获取 XML 文档。 HTTParty 在后台使用 MultiXML,默认情况下使用 Nokogiri 将返回的文档解析为 Ruby 对象的集合。 XML 文档中的某些节点应该是“1 个或多个”或“0 个或多个”元素(又名序列)的数组,但当它们仅包含单个元素时,它们仅作为父元素的值返回,而不是数组中的单个项目。托管这些 XML 文件的一方还为文档提供了 XSD,其中包含有关哪些节点应该是序列的信息。我了解 Nokogiri 有一个用于针对 XSD 验证文档的 Schema 实用程序,但有没有办法使用该模式为文档解析器提供类型提示,以便在返回的 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,所以如果有更好的解析器可以用于这种情况,我愿意尝试一下。

【问题讨论】:

  • 请阅读“minimal reproducible example”。您向我们提供了数据,但没有向我们展示您如何获得 Nokogiri 的输出,这对问题至关重要。 MultiXML 允许使用多个不同的 XML 解析器。 Nokogiri 不会返回哈希,所以其他东西正在处理数据;可能是 MultiXML,或者它使用的是 Ox,它确实返回了一个 Hash。单独使用 Nokogiri 进行处理很容易,除了 YMMV 之外我不会打扰其他任何事情。
  • 我已将示例更新为我用来测试的确切 ruby​​。 MultiXML 确实使用 Nokogiri 作为解析器。

标签: ruby xsd xml-parsing nokogiri httparty


【解决方案1】:

您的问题没有很好地提出,但听起来您可能没有正确解析数据。可以始终将单个或多个节点的内容作为数组获取,因此您只需要担心处理数组:

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 仍然是一个字符串数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    • 2011-04-28
    相关资源
    最近更新 更多