2014-04-08 4 views
0

Это было задано ранее в «REXML - How to extract a single element», но ответ не работает. По-видимому, метод text больше не доступен.Вывод массива содержимого тегов с использованием REXML?

У меня есть файл XML:

<?xml version="1.0" encoding="UTF-8"?> 
<ice_cream> 
    <flavor>Vanilla</flavor> 
</ice_cream> 

и я могу поместить его содержимое в массив с помощью REXML:

flavors = xml_file.get_elements('//flavor') 

Я получаю массив:

puts flavors[0] 

который возвращает :

<flavor>Vanilla</flavor> 

Вместо этого я хочу:

Vanilla 

Я пробовал:

flavors = xml_file.get_elements('//flavor').text 

Но, я получаю:

NoMethodError: undefined method `text' for #<Array:0x007fa7a3b94220> 

Что такое правильный способ сделать это? Я открыт для использования и других библиотек.

+1

Вы попробовали 'flavors [0] .text' – Bala

+0

Просто дайте мне содержимое' xml', пожалуйста, –

+0

Нет (показывает, что я новичок Ruby).Это сделало трюк для вытягивания текста из массива, но как мне получить только текст в массиве в первую очередь? – jcarpio

ответ

1

Использование Nokogiri. Ваш код будет вам благодарен.

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="UTF-8"?> 
<ice_cream> 
    <flavor>Vanilla</flavor> 
</ice_cream> 
EOT 

doc.search('flavor') # => [#<Nokogiri::XML::Element:0x3feb8182fc60 name="flavor" children=[#<Nokogiri::XML::Text:0x3feb8182fa44 "Vanilla">]>] 
doc.search('flavor').map(&:text) # => ["Vanilla"] 

search находит все узлы, как NodeSet, которые соответствуют селектор CSS 'flavor'.

search('flavor').map(&:text) Проходит NodeSet и применяет (map) метод text к каждому узлу, возвращая его текстовые узлы.

Если ваш XML является на самом деле что-то более сложное:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="UTF-8"?> 
<ice_cream> 
    <flavor>Vanilla</flavor> 
    <flavor>Chocolate</flavor> 
    <flavor>Strawberry</flavor> 
</ice_cream> 
EOT 

doc.search('flavor') # => [#<Nokogiri::XML::Element:0x3fcc2a577afc name="flavor" children=[#<Nokogiri::XML::Text:0x3fcc2a5778e0 "Vanilla">]>, #<Nokogiri::XML::Element:0x3fcc2a5776c4 name="flavor" children=[#<Nokogiri::XML::Text:0x3fcc2a5774bc "Chocolate">]>, #<Nokogiri::XML::Element:0x3fcc2a5772b4 name="flavor" children=[#<Nokogiri::XML::Text:0x3fcc2a572c78 "Strawberry">]>] 
doc.search('flavor').map(&:text) # => ["Vanilla", "Chocolate", "Strawberry"] 

Или:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="UTF-8"?> 
<ice_creams> 
    <ice_cream> 
     <flavor>Vanilla</flavor> 
    </ice_cream> 
    <ice_cream> 
     <flavor>Chocolate</flavor> 
    </ice_cream> 
    <ice_cream> 
     <flavor>Strawberry</flavor> 
    </ice_cream> 
</ice_creams> 
EOT 
ice_cream = doc.search('ice_cream') # => [#<Nokogiri::XML::Element:0x3fe6a91f6b00 name="ice_cream" children=[#<Nokogiri::XML::Text:0x3fe6a91f68f8 "\n  ">, #<Nokogiri::XML::Element:0x3fe6a91f681c name="flavor" children=[#<Nokogiri::XML::Text:0x3fe6a91f6600 "Vanilla">]>, #<Nokogiri::XML::Text:0x3fe6a91f63f8 "\n ">]>, #<Nokogiri::XML::Element:0x3fe6a91f1de4 name="ice_cream" children=[#<Nokogiri::XML::Text:0x3fe6a91f1bdc "\n  ">, #<Nokogiri::XML::Element:0x3fe6a91f1ac4 name="flavor" children=[#<Nokogiri::XML::Text:0x3fe6a91f1880 "Chocolate">]>, #<Nokogiri::XML::Text:0x3fe6a91f1678 "\n ">]>, #<Nokogiri::XML::Element:0x3fe6a91f13f8 name="ice_cream" children=[#<Nokogiri::XML::Text:0x3fe6a91f1074 "\n  ">, #<Nokogiri::XML::Element:0x3fe6a91f0e80 name="flavor" children=[#<Nokogiri::XML::Text:0x3fe6a91f0a98 "Strawberry">]>, #<Nokogiri::XML::Text:0x3fe6a91f0840 "\n ">]>] 
ice_cream.search('flavor').map(&:text) # => ["Vanilla", "Chocolate", "Strawberry"] 

Для поиска, Nokogiri поддерживает использование как CSS и XPath селекторы, и позволяет использовать либо в методах , если ты хочешь. search принимает как CSS, так и XPath и имеет следствия css и xpath для специальных методов CSS или XPath. at возвращает один узел и аналогичен search('some_node').first и имеет at_css и at_xpath соответственно.

0

Вот код:

require 'rexml/document' 

doc = <<-xml 
<?xml version="1.0" encoding="UTF-8"?> 
<ice_cream> 
    <flavor>Vanilla</flavor> 
</ice_cream> 
xml 

xml_doc = REXML::Document.new(doc) 
xml_doc.get_elements('//flavor').class # => Array 
xml_doc.get_elements('//flavor')[0].class # => REXML::Element 
xml_doc.get_elements('//flavor')[0].text # => "Vanilla" 

На самом деле xml_doc.get_elements('//flavor') даст вам коллекцию REXML::Element объектов. Затем вам необходимо выполнить итерацию по коллекции и вызвать метод #text на объекте REXML::Element, чтобы получить текст.

Смежные вопросы