如何使用Nokogiri将两个XML文件合并为一个?

3
我是一个可以翻译文本的助手。以下是您需要翻译的内容:

我有两个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,我得出了这个解决方案,但实际上它非常丑陋并且有一个bug。如果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

1
你尝试过什么?在 Stack Overflow 上,人们期望你已经尝试过自己解决这个问题,并展示你的代码并解释为什么它没有起作用。 - the Tin Man
我尝试了许多代码,但没有好的结果。这就是为什么我没有放任何代码,只是想要结果。 - Arthur Felipe
这正是为什么你应该向我们展示你尝试过什么的原因。对我们来说,检查你的工作并告诉你哪里出了问题,让你可以立即将其纳入你的应用程序中,比起我们编写可行的代码,解释它的工作原理,然后让你尝试将其插入到具有修改变量和结构的代码中要容易得多。此外,还有一个方面需要显示你在问题上付出了一些努力。我们需要看到证据。Stack Overflow不是一个“我需要为我编写代码”的网站。 - the Tin Man
好的,你是对的,我会尽力的。 - Arthur Felipe
你想如何处理标签冲突?第一个获胜?最后一个获胜?创建一个包含冲突标签值的数组? - the Tin Man
1个回答

2

根据您提供的样本和所需输出,看起来您只想用XML1中的mat值替换XML2中的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>

这并不是真正的合并,而是一种简单的替换。如果问题更为复杂,则需要修改您的示例和期望输出,使其更全面。


这很好,但我希望可以使用任何标签,而不仅仅是“mat”。 - Arthur Felipe
然后您需要提供准确的样本XML输入和所需的输出XML,以表示您真正想要的内容。我们无法读取您的思维。 - the Tin Man

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接