2013-09-09 6 views
3

У меня есть два XML-файлы и хотите объединить их, но теги, которые уже там не должны быть изменены:Как объединить два файла XML в один, используя Nokogiri?

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> 

I хочу, чтобы результат был таким:

<?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 
+1

Что вы пробовали? В Stack Overflow ожидается, что вы попытаетесь решить это самостоятельно, и чтобы показать свой код и дать объяснение, почему он не работает. –

+0

Я пробовал много кодов, но никаких хороших результатов. Вот почему я не поместил какой-либо код, а то, что хочу от результата. –

+0

И это точно, почему вы должны показать нам, что вы пробовали. Нам очень легко проверить вашу работу, а затем показать вам, что не так, поэтому вы можете сразу включить это в свое приложение, чем нам писать рабочий код, объяснять, как он работает, а затем попробуйте * вставить его в ваш код с измененными переменными и структурами. Кроме того, есть целый аспект, показывающий, что вы вложили некоторые усилия в вопрос. Нам нужно увидеть доказательство. Stack Overflow не является сайтом «Мне нужен код, написанный для меня». –

ответ

2

на основе ваших образцов и желаемый результат в этом случае вы просто хотите заменить значение mat в xml2 со значением mat от XML1.

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> 

Это на самом деле не слияние, это просто замена. Если проблема больше, тогда ваши примеры и желаемый результат необходимо изменить, чтобы быть более полными.

+0

Это хорошо, но я хочу, чтобы с любым тегом. Не только «коврик». –

+0

Затем вам необходимо предоставить точный образец XML-ввода и желаемый выходной XML, который представляет то, что вы действительно хотите. Мы не можем читать ваши мысли. –