2009-08-13 29 views
14

Tôi muốn trích xuất các phần của một tệp XML và ghi chú rằng tôi đã trích xuất một phần nào đó trong tệp đó, như "một thứ gì đó đã được trích xuất".Chèn và xóa các nút và các phần tử XML bằng cách sử dụng Nokogiri

Tôi đang cố gắng để làm điều này với Nokogiri, nhưng nó có vẻ không thực sự được ghi chép lại về cách:

  1. xóa tất cả Childs của một sự thay đổi <Nokogiri::XML::Element>
  2. các inner_text đó yếu tố hoàn

Bất kỳ manh mối nào?

+0

Nokogiri của Hướng dẫn cho [Sửa đổi một HTML/XML Tài liệu] (http://nokogiri.org/tutorials/modifying_an_html_xml_document.html) đề cập đến điều này. Ngoài ra 'node.unlink' sẽ xóa nó khỏi DOM. –

+0

Xem "[yêu cầu]". Như vậy, đây là thiếu thông tin quan trọng như một ví dụ XML tối thiểu cho đầu vào và đầu ra dự kiến, cộng với mã được viết để giải quyết vấn đề. –

Trả lời

3

Bạn có thể làm điều đó như thế này:

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

Trong khi đó sẽ loại bỏ tất cả trẻ em trong thẻ <note>, tôi không chắc chắn làm thế nào để "thay đổi inner_text" của tất cả các yếu tố lưu ý. Tôi nghĩ rằng inner_text không áp dụng cho Phần tử Nokogiri :: XML ::.

14

Nokogiri làm việc này khá dễ dàng. Sử dụng this document làm ví dụ, đoạn mã sau sẽ tìm thấy tất cả vitamins thẻ, loại bỏ con cái của họ (và trẻ em của trẻ em, vv), và thay đổi văn bản bên trong của họ để nói "lấy trẻ em.":

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 

Một trao food nút sẽ đi từ tìm kiếm như thế này:

<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> 

này:

<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

Ví dụ Nokogiri trước đặt tôi trong r ight hướng, nhưng sử dụng doc.search để lại một bị thay đổi //vitamins, vì vậy tôi sử dụng 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 

mà kết quả trong:

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

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

Đây là những gì tôi muốn làm:

Phân tích một số XML đầu tiên:

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 

Nếu tôi muốn xóa nội dung của nút, tôi có thể xóa ove nó children hoặc gán nil nội dung của nó:

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\"/>" 

hay:

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\"/>" 

Nếu tôi muốn trích xuất văn bản từ một nút để sử dụng một số cách khác:

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 " 

hoặc :

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 "] 

hoặc bất kỳ cách nào khác bạn muốn xé văn bản.

Và, nếu bạn muốn đánh dấu mà bạn đã xóa đoạn Phúc Âm:

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

Bạn cũng có thể sử dụng một bình luận XML thay vì:

doc.at('food').children = '<!-- REMOVED -->' 
doc.at('food').to_xml # => "<food>\n <!-- REMOVED -->\n</food>" 
Các vấn đề liên quan