2013-02-26 2 views
0

Я использую rest-client для возврата XML с другого сайта и попытки использовать Nokogiri для его анализа. XML выглядит так:Анализ XML с использованием Nokogiri

<?xml version="1.0" encoding="UTF-8"?> ... 
<MXAUTOKESet> 
    <AUTOKEY> 
    <AUTOKEYID>27</AUTOKEYID> 
    <AUTOKEYNAME>WORKORDERNUM</AUTOKEYNAME> 
    <ORGID>xxxx</ORGID> 
    <PREFIX>12-</PREFIX> 
    <SEED>38979</SEED> 
    ... 

Я хочу извлечь номера «PREFIX» и «SEED».

мой взгляд код выглядит следующим образом:

<% xml_data = RestClient.get "URL (sorry can't display it in this question)" %> 
<%= xml_doc = Nokogiri::XML(xml_data)%> 

Вторая строка отображает возвращенную XML на странице, так что, я знаю, остальное-клиент работает, но я не знаю, как получить доступ к проанализированный XML.


Update1:

я смог creationDateTime из заголовка XML, используя следующее. Но я до сих пор не могу получить значение SEED:

<%= doc = Nokogiri::XML(xml_data)%>  
<h4>Creation Date</h4> 
<% root = doc.root %> 
<%= root["creationDateTime"] %> 
<h4>SEED</h4> 
<%= seed = root.xpath("SEED").text %> 

или

<%= seed = doc.xpath("//SEED").inner_text %> 
+2

Пожалуйста, не ставьте всю эту логику на ваш взгляд. –

+0

Марк - должен ли он идти в контроллер или модель? (Извините - я новичок в этом) – Reddirt

+1

@Reddirt Контроллер. Извлеките фрагменты из XML в контроллере, а затем поместите их туда, где вы хотите увидеть их в представлении. – Phrogz

ответ

2

Там в пару вещей неправильно в вашем коде, так вот как я бы делать вещи:

Начало с этим кодом:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="UTF-8"?> 
<MXAUTOKESet> 
    <AUTOKEY> 
    <AUTOKEYID>27</AUTOKEYID> 
    <AUTOKEYNAME>WORKORDERNUM</AUTOKEYNAME> 
    <ORGID>xxxx</ORGID> 
    <PREFIX>12-</PREFIX> 
    <SEED>38979</SEED> 
EOT 

puts doc.to_xml 

я получаю этот выход , показывая, что Nokogiri сделал немного исправить вверх, чтобы закрыть открытые метки, обеспечивая достаточно правильный кусок XML:

<?xml version="1.0" encoding="UTF-8"?> 
<MXAUTOKESet> 
    <AUTOKEY> 
    <AUTOKEYID>27</AUTOKEYID> 
    <AUTOKEYNAME>WORKORDERNUM</AUTOKEYNAME> 
    <ORGID>xxxx</ORGID> 
    <PREFIX>12-</PREFIX> 
    <SEED>38979</SEED> 
</AUTOKEY></MXAUTOKESet> 

xpath ожидает XPath сбруя, и возвращает NodeSet, который, как массив узлов:

doc.xpath("//SEED").class 
=> Nokogiri::XML::NodeSet 
doc.xpath("//SEED") 
=> [#<Nokogiri::XML::Element:0x3fdf890e3208 name="SEED" children=[#<Nokogiri::XML::Text:0x3fdf890e3000 "38979">]>] 

Проблема заключается в том, xpath и его css коллега будет возвращать каждое вхождение своей цели они находят в документе, который не является что вы хотите, если есть два или более тега «SEED». Вместо этого вы хотите получить at или at_xpath или at_css, которые возвращают первое обнаруженное событие; Я рекомендую использовать at (или search) и CSS для ваших первых тестов, поскольку их легче понять, чем XPath.

Старинная использовать at и CSS:

doc.at("SEED").class 
=> Nokogiri::XML::Element 
doc.at("SEED") 
=> #<Nokogiri::XML::Element:0x3fdf890e3208 name="SEED" children=[#<Nokogiri::XML::Text:0x3fdf890e3000 "38979">]> 

Обратите внимание, что doc.at("SEED") возвратил "Nokogiri :: XML :: Элемент", который, как Nokogiri описывает узел, вместо (массив AKA) NodeSet из xpath (AKA search).

Получение в тексте просто, как только у вас есть узел:

doc.at("SEED").text 
=> "38979" 

Вот как я бы захватить оба значения и назначить их к двум переменным, учитывая небольшой XML-фрагмент:

seed, prefix = %w[SEED PREFIX].map{ |t| doc.at(t).text } 
=> ["38979", "12-"] 
+0

Doc.at ("SEED"). Текст работал !!!!!!! Спасибо вам! – Reddirt

1

Последняя строка кода, puts doc.xpath("//SEED").inner_text, должен работать. Есть ли в реальных XML пространства имен? Если это произойдет, попробуйте вместо этого: puts doc.css("SEED").inner_text

+0

Использование 'xpath' и' css' будет работать с простым XML-файлом, подобным этому, но не удастся, возвращая непреднамеренные результаты, если есть несколько вхождений тега ''. –