【问题标题】:How do I merge two XML files into one using Nokogiri?如何使用 Nokogiri 将两个 XML 文件合并为一个?
【发布时间】:2013-09-10 01:56:38
【问题描述】:

我有两个 XML 文件,想合并它们,但是已经存在的标签不应该更改:

XML 1:

<?xml version="1.0"?>
<formX xmlns="sdu:x">
  <identify>
    <mat>8</mat>
  </identify>
</formX>

XML 2:

<?xml version="1.0"?>
<formX xmlns="sdu:x">
  <identify>
    <mat>9999</mat>
    <name>John Smith</name>
  </identify>
</formX>

我希望结果是这样的:

<?xml version="1.0"?>
<formX xmlns="sdu:x">
  <identify>
    <mat>8</mat>
    <name>John Smith</name>
  </identify>
</formX>

以前的标签应该具有相同的值,但添加了新的值。 使用 Nokogiri 可以吗?怎么样?

起初我尝试不使用 Nokogiri 使用:

xml1 = Hash.from_xml('<?xml version="1.0"?>
<formX xmlns="sdu:x">
  <identify>
    <mat>8</mat>
  </identify>
</formX>')

但是当我转换回 xml (xml1.to_xml) 时格式错误:

"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n  <formX>\n    <xmlns>sdu:x</xmlns>\n    <identify>\n      <mat>8</mat>\n    </identify>\n  </formX>\n</hash>\n"

使用 Nokogiri,我想出了这个解决方案,但实际上,它是如此丑陋并且有一个错误。如果 xml2 没有元素,它将崩溃:

require 'nokogiri'

s = "<formAposentadoria xmlns=\"spu:aposentadoria\"><identificacao><matricula>8</matricula></identificacao></formAposentadoria>"
xml1 = Nokogiri::XML.parse s

s2 = "<formAposentadoria xmlns=\"spu:aposentadoria\"><identificacao><matricula>9</matricula><nome>John</nome></identificacao></formAposentadoria>"
xml2 = Nokogiri::XML.parse s2

def node_list elem, &proc
  return [] unless elem.class == Nokogiri::XML::Element
  str = proc.call(elem)
  [str] + elem.children.inject([]){|a,c| a+node_list(c,&proc)}.map{|e| "#{str}/#{e}"}
end

node_list(xml1.root){|e| e.name}.each do |x|
  caminho = '//xmlns:' + x.gsub('/', '/xmlns:')
  puts caminho
  if xml2.at_xpath( caminho ).children.children.count == 0
    xml2.at_xpath( caminho ).content = xml1.at_xpath( caminho ).content
  end
end

puts xml2.to_xml

【问题讨论】:

  • 你试过什么?在 Stack Overflow 上,您应该尝试自己解决这个问题,并展示您的代码并解释为什么它不起作用。
  • 我尝试了很多代码,但没有好的结果。这就是为什么我没有放任何代码,而是我想要的结果。
  • 这正是您应该向我们展示您尝试过的东西的原因。与我们编写工作代码、解释其工作原理然后让您尝试 i> 使用修改后的变量和结构将其插入到您的代码中。另外,整个方面都表明你在这个问题上付出了一些努力。我们需要看到证据。 Stack Overflow 不是“我需要为我编写代码”的网站。
  • 好的。你是对的,我会尽我所能。
  • 您希望如何处理标签冲突?第一个赢?最后一个赢了?为碰撞标签创建一个值数组?

标签: ruby xml nokogiri


【解决方案1】:

根据您的示例和所需的输出,您似乎只想将 XML2 中的 mat 值替换为 XML1 中的 mat 值。

require 'nokogiri'

xml1 = Nokogiri::XML('<?xml version="1.0"?>
<formX xmlns="sdu:x">
  <identify>
    <mat>8</mat>
  </identify>
</formX>')

xml2 = Nokogiri::XML('<?xml version="1.0"?>
<formX xmlns="sdu:x">
  <identify>
    <mat>9999</mat>
    <name>John Smith</name>
  </identify>
</formX>')

xml2.at('mat').content = xml1.at('mat').content

puts xml2.to_xml

哪些输出:

<?xml version="1.0"?>
<formX xmlns="sdu:x">
  <identify>
    <mat>8</mat>
    <name>John Smith</name>
  </identify>
</formX>

这并不是真正的合并,而是简单的替换。如果问题还有更多问题,则需要修改您的示例和所需的输出以使其更全面。

【讨论】:

  • 这很好,但我想要任何标签。不仅仅是“垫子”。
  • 那么您需要提供准确的示例 XML 输入和代表您真正想要的输出 XML。我们无法读懂你的想法。
猜你喜欢
  • 1970-01-01
  • 2012-04-24
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-12
  • 2018-07-30
  • 1970-01-01
相关资源
最近更新 更多