2011-03-15 18 views
6

करने के लिए एक नए नोड जोड़ने के लिए मैं कैसे एक सरल एक्सएमएल फ़ाइल है, items.xml:एक्सएमएल

<?xml version="1.0" encoding="UTF-8" ?> 

<items> 
    <item> 
    <name>mouse</name> 
    <manufacturer>Logicteh</manufacturer> 
    </item> 
    <item> 
    <name>keyboard</name> 
    <manufacturer>Logitech - Inc.</manufacturer> 
    </item> 
    <item> 
    <name>webcam</name> 
    <manufacturer>Logistech</manufacturer> 
    </item> 
</items> 

मैं निम्नलिखित कोड के साथ एक नया नोड डालने के लिए कोशिश कर रहा हूँ:

require 'rubygems' 
require 'nokogiri' 

f = File.open('items.xml') 
@items = Nokogiri::XML(f) 
f.close 

price = Nokogiri::XML::Node.new "price", @items 
price.content = "10" 

@items.xpath('//items/item/manufacturer').each do |node| 
    node.add_next_sibling(price) 
end 

file = File.open("items_fixed.xml",'w') 
file.puts @items.to_xml 
file.close 

हालांकि इस कोड को केवल पिछले <manufacturer> नोड, items_fixed.xml के बाद एक नया नोड जोड़ता है:

<?xml version="1.0" encoding="UTF-8"?> 
<items> 
    <item> 
    <name>mouse</name> 
    <manufacturer>Logitech</manufacturer> 
    </item> 
    <item> 
    <name>keyboard</name> 
    <manufacturer>Logitech</manufacturer> 
    </item> 
    <item> 
    <name>webcam</name> 
    <manufacturer>Logitech</manufacturer><price>10</price> 
    </item> 
</items> 

क्यों?

+0

आप इसे बहुत कठिन बनाते हैं। नोकोगिरी एक स्ट्रिंग का उपयोग करके नोड्स को जोड़ना आसान बनाता है, जो उसके बाद एक नए नोड में पार्स करता है। नीचे मेरा जवाब देखें। –

उत्तर

12

Node (एक पेड़ में किसी विशेष स्थान पर संरचित XML डेटा का एक विशेष टुकड़ा) और "नोड टेम्पलेट" के बीच अंतर करना उपयोगी होगा जो डेटा की संरचना है।

नोकोगिरी (और अधिकांश अन्य एक्सएमएल पुस्तकालय) केवल आपको Node एस निर्दिष्ट करने की अनुमति देते हैं, नोड टेम्पलेट्स नहीं। तो जब आपने price = Nokogiri::XML::Node.new "price", @items बनाया, तो आपके पास एक विशेष स्थान पर मौजूद डेटा का एक विशेष टुकड़ा था, लेकिन अभी तक इस जगह को परिभाषित नहीं किया था।

जब आपने इसे पहले <item> में जोड़ा, तो आपने इसकी जगह परिभाषित की। जब आपने इसे दूसरे <item> में जोड़ा, तो आपने इसे अपनी जगह से हटा दिया और इसे एक नए स्थान पर रखा। उस बिंदु पर यह Node केवल दूसरे <item> में दिखाई दिया। यह तब भी जारी रहता है जब आप एक ही Node प्रत्येक आइटम में जोड़ते हैं, जब तक कि आप अंतिम <item> तक नहीं पहुंच जाते, जहां नोड रहता है।

नोकोगिरी के पास नोड टेम्पलेट निर्दिष्ट करने का कोई तरीका नहीं है। आपको क्या करने की जरूरत है:

@items.xpath('//items/item/manufacturer').each do |node| 
    price = Nokogiri::XML::Node.new "price", @items 
    price.content = "10" 
    node.add_next_sibling(price) 
end 
+0

मैंने डीबगर में समझाया गया सटीक व्यवहार देखा लेकिन इसे समझ में नहीं आया। आपकी व्याख्या और आपके उत्तर के लिए धन्यवाद! –

+2

वैकल्पिक रूप से, आप इसे किसी नए स्थान पर डालने से पहले नोड को क्लोन करने के लिए ['नोड # डुपी'] (http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Node.html#M000469) का उपयोग करना चाह सकते हैं । – Phrogz

+0

अच्छा स्पष्टीकरण .. पिछले 3-4 दिनों से मुझे एक ही समस्या थी। अब मुझे पता चला कि यह क्यों हो रहा था। ओपी और आप के लिए धन्यवाद। –

2

मैं इस के साथ शुरू होता है:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="UTF-8"?> 
<items> 
    <item> 
    <name>mouse</name> 
    <manufacturer>Logitech</manufacturer> 
    </item> 
    <item> 
    <name>keyboard</name> 
    <manufacturer>Logitech - Inc.</manufacturer> 
    </item> 
</items> 
EOT 

doc.search('manufacturer').each { |n| n.after('<price>10</price>') } 

कौन सा में परिणाम:

puts doc.to_xml 
# >> <?xml version="1.0" encoding="UTF-8"?> 
# >> <items> 
# >> <item> 
# >>  <name>mouse</name> 
# >>  <manufacturer>Logitech</manufacturer><price>10</price> 
# >> </item> 
# >> <item> 
# >>  <name>keyboard</name> 
# >>  <manufacturer>Logitech - Inc.</manufacturer><price>10</price> 
# >> </item> 
# >> </items> 

यह इस पर निर्माण करने के लिए अलग-अलग मान सम्मिलित करने के लिए आसान है कीमत।