【问题标题】:Ruby - XML to Hash and then Hash to XML, both XMLs are not sameRuby - XML 到 Hash,然后 Hash 到 XML,两个 XML 不一样
【发布时间】:2018-05-22 13:24:25
【问题描述】:

我有一个类似的 XML:

<response xmlns:msg="http://schemas.xyzlabs.net/2010/messaging/" xmlns:ld="http://schemas.xyzlabs.net/2010/lab-data/">
  <msg:trb proRefId="12345" tesComNa="Xyz Laboratories,Inc.">
    <sample ttz="020206b01" id="1898-57" name="Adam, Franklin" />
  </msg:trb>
</response>

我应该在 ruby​​ 中读取 XML,并在 UI(文本区域内)中以可读性强的 HASH 格式显示它,用户可以在其中编辑 HASH 中的值。

然后我应该从哈希中重新生成 XML。

但是,初始 XML 和最终 XML 不同

代码

XML > 哈希

h = Hash.from_xml('
  <response xmlns:msg="http://schemas.xyzlabs.net/2010/messaging/" xmlns:ld="http://schemas.xyzlabs.net/2010/lab-data/">
    <msg:trb proRefId="12345" tesComNa="Xyz Laboratories,Inc.">
      <sample ttz="020206b01" id="1898-57" name="Adam, Franklin" />
    </msg:trb>
  </response>
')

输出

#{
#  "response" => {
#    "xmlns:msg"=>"http://schemas.xyzlabs.net/2010/messaging/",
#    "xmlns:ld"=>"http://schemas.xyzlabs.net/2010/lab-data/",
#    "trb" => {
#      "proRefId" => "12345",
#      "tesComNa" => "Xyz Laboratories,Inc.",
#      "sample" => {
#        "ttz" => "020206b01",
#        "id" => "1898-57",
#        "name" => "Adam, Franklin"
#      }
#    }
#  }
#}

假设用户修改了上述内容,我正在尝试将修改后的 HASH 再次转换为 XML:

哈希 > XML

h["response"].to_xml(root: "response")

输出

<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<response>
  <xmlns:msg>
    http://schemas.xyzlabs.net/2010/messaging/
  </xmlns:msg>
  <xmlns:ld>
    http://schemas.xyzlabs.net/2010/lab-data/undefined
  </undefinedxmlns:ld>
    undefined
  <trb>
    <proRefId>12345</proRefId>    
    <tesComNa>Xyz Laboratories,Inc.</tesComNa>    
    <sample>      
      <ttz>020206b01</ttz>      
      <id>1898-57</id>      
      <name>Adam, Franklin</name>    
  </sample>
    undefined
    </trb>
  undefined
</response>

我看到很多undefined,并且任何节点的属性都会转换为节点本身。

如何在仅修改其各自值的情况下恢复原始 XML(由用户完成)?

【问题讨论】:

  • 是的,我在这里看不到简单的方法,因为哈希不能在键上具有属性。这就是为什么 xml->hash 转换使它们成为单独的键值对,而这些键值对又正确地成为独立的标签。
  • @SergioTulentsev 另外,另一个问题是,如果任何标签有文本,例如:&lt;sample ttz="020206b01" id="1898-57" name="Adam, Franklin"&gt;Some Text&lt;/sample&gt;,那么转换成 HASH 会跳过属性
  • 这是一个普遍的问题:数据从一个数据模型 A 到另一个模型 B 的转换是不可逆的,除非这两个数据模型是同构的。要么 A 中的两个值在 B 中具有相同的表示形式,要么 B 中的两个值在 A 中具有相同的表示形式。您的问题在数学上是无法解决的。

标签: ruby-on-rails ruby xml hash


【解决方案1】:

我认为这可能与您的环境有关。我已经用 Rails 控制台(Rails 5.1.4)测试了你的代码,它按预期工作:

[1] pry(main)> h = Hash.from_xml('
[1] pry(main)*   <response xmlns:msg="http://schemas.xyzlabs.net/2010/messaging/" xmlns:ld="http://schemas.xyzlabs.net/2010/lab-data/">
[1] pry(main)*     <msg:trb proRefId="12345" tesComNa="Xyz Laboratories,Inc.">
[1] pry(main)*       <sample ttz="020206b01" id="1898-57" name="Adam, Franklin" />
[1] pry(main)*     </msg:trb>
[1] pry(main)*   </response>
[1] pry(main)* ')
=> {"response"=>
  {"xmlns:msg"=>"http://schemas.xyzlabs.net/2010/messaging/",
   "xmlns:ld"=>"http://schemas.xyzlabs.net/2010/lab-data/",
   "trb"=>
    {"proRefId"=>"12345",
     "tesComNa"=>"Xyz Laboratories,Inc.",
     "sample"=>{"ttz"=>"020206b01", "id"=>"1898-57", "name"=>"Adam, Franklin"}}}}

[2] pry(main)> h['response']['trb']['tesComNa'] = 'StackOverflow'
=> "StackOverflow"

[3] pry(main)> puts h["response"].to_xml(root: "response")
<?xml version="1.0" encoding="UTF-8"?>
<response>
  <xmlns:msg>http://schemas.xyzlabs.net/2010/messaging/</xmlns:msg>
  <xmlns:ld>http://schemas.xyzlabs.net/2010/lab-data/</xmlns:ld>
  <trb>
    <proRefId>12345</proRefId>
    <tesComNa>StackOverflow</tesComNa>
    <sample>
      <ttz>020206b01</ttz>
      <id>1898-57</id>
      <name>Adam, Franklin</name>
    </sample>
  </trb>
</response>

【讨论】:

  • 不,不符合预期。 xmlns:msg 现在是它自己的标签,但它应该是一个属性。
  • 恐怕你误解了这个问题。您可以清楚地看到 XML 是不同的。例如:- xmlns:msg 不应该是一个单独的标签。它应该是response的属性
  • 现在我明白你的意思了。我认为主要问题是undefined。在这种情况下,我认为最简单的解决方案是使用 gem 来解析 XML(例如 Nokogiri)。
  • 我确实使用 Nokogiri。但是,我不确定如何用它来实现上述场景
猜你喜欢
  • 2018-01-15
  • 2020-05-11
  • 2017-02-24
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 2012-04-19
  • 2016-06-14
相关资源
最近更新 更多