Следующее должно работать для вас, предполагая, что пространство имен dms
всегда одинаково
doc.xpath('//CONTENT/dms:ComplexResponse', dms: 'http://dmsmanagerservice')
.xpath('@ErrorCode | @ErrorDescription')
.each_with_object({}) do |e,obj|
obj[e.name] = e.text
end
#=> {"ErrorCode"=>"430", "ErrorDescription"=>"null : PrivacyUE Mancante"}
Вы уже понимаете, как попали в // CONTENT, поэтому оттуда мы используем dms: ComplexResponse для более глубокой навигации, нотак как это пространство имен, мы должны предоставить ссылку на пространство имен, например dms: 'http://dmsmanagerservice'
.
Затем мы выбираем интересующие нас атрибуты @ErrorCode
и @ErrorDescription
.
В XPath
труба |
означает UNION (подумайте И), поэтому мы хотим выбрать оба.
Затем мы просто создаем Hash
, используя name
в качестве ключа и text
в качестве значения.
XPath Cheatsheet - Полезный ресурс, есливам нужна дополнительная ссылка
Обновление
Вы спрашивали об условных обозначениях, поэтому я бы предложил
ndoc = Nokogiri::XML(doc)
namespaces = ndoc.collect_namespaces
response = ndoc.xpath("//CONTENT/dms:ComplexResponse", namespaces)
if response.xpath("self::node()[@ErrorCode != '' and @ErrorDescription != '']").any?
response.xpath("@ErrorCode | @ErrorDescription")
.each_with_object({}) do |e,obj|
obj[e.name] = e.text
end
else
response.xpath('dms:Element/@Name | dms:Element/text()',namespaces)
.each_slice(2)
.map {|s| s.map(&:text)}.to_h
end
Эта проверка позволяет проверить, есть лиErrorCode и и ErrorDescription, если так, то Hash, как первоначально предлагалось.Если нет, то он возвращает все элементы dms: Elements как Hash
, поэтому {"DMSVERSION"=>"2.7"}
в этом случае Функциональный пример