Ответ 1
Нори фактически не отбрасывает атрибуты, они просто не печатаются.
Если вы запустите ruby script:
require 'nori'
data = Nori.new(empty_tag_value: true).parse(<<XML)
<?xml version="1.0"?>
<root>
<objects>
<object>
<fields>
<field name="Name">The name</field>
<field name="Description">A description</field>
</fields>
</object>
</objects>
</root>
XML
field_list = data['root']['objects']['object']['fields']['field']
puts "text: '#{field_list[0]}' data: #{field_list[0].attributes}"
puts "text: '#{field_list[1]}' data: #{field_list[1].attributes}"
Вы должны получить вывод
["The name", "A description"]
text: 'The name' data: {"name"=>"Name"}
text: 'A description' data: {"name"=>"Description"}
Что ясно показывает, что атрибут есть, но не отображается методом inspect
(функция p(x)
совпадает с puts x.inspect
).
Вы заметите, что puts field_list.inspect
выводит ["The name", "A description"]
. но field_list[0].attributes
печатает ключ атрибута и данные.
Если вы хотите, чтобы pp
отображал это, вы можете перегрузить метод inspect
в Nori::StringWithAttributes
.
class Nori
class StringWithAttributes < String
def inspect
[attributes, String.new(self)].inspect
end
end
end
Или, если вы хотите изменить вывод, вы можете перегрузить метод self.new
, чтобы он возвращал другую структуру данных.
class Nori
class MyText < Array
def attributes=(data)
self[1] = data
end
attr_accessor :text
def initialize(text)
self[0] = text
self[1] = {}
end
end
class StringWithAttributes < String
def self.new(x)
MyText.new(x)
end
end
end
И получить доступ к данным в виде кортежа
puts "text: '#{data['root']['objects']['object']['fields']['field'][0].first}' data: #{ data['root']['objects']['object']['fields']['field'][0].last}"
Это позволит сделать так, чтобы данные были как JSON или YAML, так как текстовые элементы выглядели бы как массивы с двумя элементами.
pp
также работает.
{"root"=>
{"objects"=>
{"object"=>
{"fields"=>
{"field"=>
[["The name", {"name"=>"Name"}],
["A description", {"name"=>"Description"}]]},
"bob"=>[{"@id"=>"id1"}, {"@id"=>"id2"}],
"bill"=>
[{"p"=>["one", {}], "@id"=>"bid1"}, {"p"=>["two", {}], "@id"=>"bid2"}],
"@id"=>"1"}}}}
Это должно делать то, что вы хотите.
require 'awesome_print'
require 'nori'
# Copyright (c) 2016 G. Allen Morris III
#
# Awesome Print is freely distributable under the terms of MIT license.
# See LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
module AwesomePrint
module Nori
def self.included(base)
base.send :alias_method, :cast_without_nori, :cast
base.send :alias_method, :cast, :cast_with_nori
end
# Add Nori XML Node and NodeSet names to the dispatcher pipeline.
#-------------------------------------------------------------------
def cast_with_nori(object, type)
cast = cast_without_nori(object, type)
if defined?(::Nori::StringWithAttributes) && object.is_a?(::Nori::StringWithAttributes)
cast = :nori_xml_node
end
cast
end
#-------------------------------------------------------------------
def awesome_nori_xml_node(object)
return %Q|["#{object}", #{object.attributes}]|
end
end
end
AwesomePrint::Formatter.send(:include, AwesomePrint::Nori)
data = Nori.new(empty_tag_value: true).parse(<<XML)
<?xml version="1.0"?>
<root>
<objects>
<object>
<fields>
<field name="Name">The name</field>
<field name="Description">A description</field>
</fields>
</object>
</objects>
</root>
XML
ap data
поскольку вывод:
{
"root" => {
"objects" => {
"object" => {
"fields" => {
"field" => [
[0] ["The name", {"name"=>"Name"}],
[1] ["A description", {"name"=>"Description"}]
]
}
}
}
}
}