2009-08-13 20 views
14

Chcę wyodrębnić części pliku XML i zanotować, że wyodrębniłem część z tego pliku, na przykład "tutaj coś zostało wyodrębnione".Wstawianie i usuwanie węzłów XML i elementów za pomocą Nokogiri

Próbuję to zrobić z Nokogiri, ale wydaje się nie być naprawdę udokumentowane na temat:

  1. usunąć wszystkie dzieciaki o <Nokogiri::XML::Element>
  2. zmienić inner_text tego kompletnego elementu

Jakieś wskazówki?

+0

Poradniki Nokogiri za [Modyfikacja HTML/XML Dokument] (http://nokogiri.org/tutorials/modifying_an_html_xml_document.html) obejmują to. Również 'node.unlink' usunie go z DOM. –

+0

Zobacz "[pytanie]". Brakuje ważnych informacji, takich jak minimalny przykład XML dla danych wejściowych i oczekiwanych wyników oraz kod, który został napisany w celu rozwiązania problemu. –

Odpowiedz

3

Można to zrobić tak:

doc=Nokogiri::XML(your_document) 
note=doc.search("note") # find all tags with the node_name "note" 
note.remove 

Mimo, że usunie wszystkie dzieci w tagu <note>, nie jestem pewien, jak „zmienić inner_text” wszystkich elementów notatek. Myślę, że inner_text nie ma zastosowania do elementu Nokogiri :: XML ::.

14

Nokogiri sprawia, że ​​to całkiem proste. Korzystanie this document jako przykład, następujący kod znajdzie wszystkie vitamins tagów usunąć swoje dzieci (i dzieci dzieci, etc.), a także zmienić ich wewnętrzną tekst do powiedzenia „usunięty dzieci.”:

require 'nokogiri' 

io = File.open('sample.xml', 'r') 
doc = Nokogiri::XML(io) 
io.close 

doc.search('//vitamins').each do |node| 
    node.children.remove 
    node.content = 'Children removed.' 
end 

Dany food węzeł pójdzie patrząc tak:

<food> 
    <name>Avocado Dip</name> 
    <mfr>Sunnydale</mfr> 
    <serving units="g">29</serving> 
    <calories total="110" fat="100"/> 
    <total-fat>11</total-fat> 
    <saturated-fat>3</saturated-fat> 
    <cholesterol>5</cholesterol> 
    <sodium>210</sodium> 
    <carb>2</carb> 
    <fiber>0</fiber> 
    <protein>1</protein> 
    <vitamins> 
     <a>0</a> 
     <c>0</c> 
    </vitamins> 
    <minerals> 
     <ca>0</ca> 
     <fe>0</fe> 
    </minerals> 
</food> 

do tego:

<food> 
    <name>Avocado Dip</name> 
    <mfr>Sunnydale</mfr> 
    <serving units="g">29</serving> 
    <calories total="110" fat="100"/> 
    <total-fat>11</total-fat> 
    <saturated-fat>3</saturated-fat> 
    <cholesterol>5</cholesterol> 
    <sodium>210</sodium> 
    <carb>2</carb> 
    <fiber>0</fiber> 
    <protein>1</protein> 
    <vitamins>Children removed.</vitamins> 
    <minerals> 
     <ca>0</ca> 
     <fe>0</fe> 
    </minerals> 
</food> 
3

Poprzedni przykład Nokogiri postawił mnie w R kierunek rawo, ale przy użyciu doc.search lewo nieprawidłowy //vitamins, więc użyłem CSS:

require "rubygems" 
require "nokogiri" 

f = File.open("food.xml") 
doc = Nokogiri::XML(f) 

doc.css("food vitamins").each do |node| 
    puts "\r\n[debug] Before: vitamins= \r\n#{node}" 
    node.children.remove 
    node.content = "Children removed" 
    puts "\r\n[debug] After: vitamins=\r\n#{node}" 
end 
f.close 

co skutkuje:

debug] Before: vitamins= 
<vitamins> 
     <a>0</a> 
     <c>0</c> 
    </vitamins> 

[debug] After: vitamins= 
<vitamins>Children removed</vitamins> 
2

Oto co zrobię:

Przetwarza niektóre XML pierwszy:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0"?> 
<?xml-stylesheet type="text/css" href="nutrition.css"?> 
<nutrition> 

    <daily-values> 
    <total-fat units="g">65</total-fat> 
    <saturated-fat units="g">20</saturated-fat> 
    <cholesterol units="mg">300</cholesterol> 
    <sodium units="mg">2400</sodium> 
    <carb units="g">300</carb> 
    <fiber units="g">25</fiber> 
    <protein units="g">50</protein> 
    </daily-values> 

    <food> 
    <name>Avocado Dip</name> 
    <mfr>Sunnydale</mfr> 
    <serving units="g">29</serving> 
    <calories total="110" fat="100"/> 
    <total-fat>11</total-fat> 
    <saturated-fat>3</saturated-fat> 
    <cholesterol>5</cholesterol> 
    <sodium>210</sodium> 
    <carb>2</carb> 
    <fiber>0</fiber> 
    <protein>1</protein> 
    <vitamins> 
     <a>0</a> 
     <c>0</c> 
    </vitamins> 
    <minerals> 
     <ca>0</ca> 
     <fe>0</fe> 
    </minerals> 
    </food> 

</nutrition> 
EOT 

Jeśli chcę usunąć zawartość węzła, mogę usunąć Ove jego children lub przypisać nil do jej treści:

doc.at('total-fat').to_xml # => "<total-fat units=\"g\">65</total-fat>" 
doc.at('total-fat').children.remove 
doc.at('total-fat').to_xml # => "<total-fat units=\"g\"/>" 

czyli

doc.at('saturated-fat').to_xml # => "<saturated-fat units=\"g\">20</saturated-fat>" 
doc.at('saturated-fat').content = nil 
doc.at('saturated-fat').to_xml # => "<saturated-fat units=\"g\"/>" 

Jeśli chcę wyodrębnić tekst z węzła do użytku w jakiś inny sposób:

food = doc.at('food').text 
# => "\n Avocado Dip\n Sunnydale\n 29\n \n 11\n 3\n 5\n 210\n 2\n 0\n 1\n \n  0\n  0\n \n \n  0\n  0\n \n " 

lub :

food = doc.at('food').children.map(&:text) 
# => ["\n ", 
#  "Avocado Dip", 
#  "\n ", 
#  "Sunnydale", 
#  "\n ", 
#  "29", 
#  "\n ", 
#  "", 
#  "\n ", 
#  "11", 
#  "\n ", 
#  "3", 
#  "\n ", 
#  "5", 
#  "\n ", 
#  "210", 
#  "\n ", 
#  "2", 
#  "\n ", 
#  "0", 
#  "\n ", 
#  "1", 
#  "\n ", 
#  "\n  0\n  0\n ", 
#  "\n ", 
#  "\n  0\n  0\n ", 
#  "\n "] 

lub jakkolwiek chcesz zmodyfikować tekst.

I, jeśli chcesz, aby zaznaczyć, że usunęliśmy tekst:

doc.at('food').content = 'REMOVED' 
doc.at('food').to_xml # => "<food>REMOVED</food>" 

Można również używać komentarz XML Zamiast:

doc.at('food').children = '<!-- REMOVED -->' 
doc.at('food').to_xml # => "<food>\n <!-- REMOVED -->\n</food>" 
Powiązane problemy