7

適度に複雑な XML 構造 (数十の要素、数百の属性) があり、XSD がなく、オブジェクト モデルを作成したい場合、ボイラープレートの from_xml() および to_xml() メソッドを作成しないようにするためのエレガントな方法は何ですか?

たとえば、次のようになります。

<Foo bar="1"><Bat baz="blah"/></Foo>

次のエンドレス シーケンスを記述しないようにするにはどうすればよいですか。

class Foo
  attr_reader :bar, :bat

  def from_xml(el)
     @bar = el.attributes['bar']
     @bat = Bat.new()
     @bat.from_xml(XPath.first(el, "./bat")
  end
 etc...  

オブジェクト構造を明示的に作成しても構いません。高レベルのプログラミングで処理できると確信しているのはシリアライゼーションです...


クラスごとに1行または2行を節約しようとはしていません(from_xmlの動作を初期化子またはクラスメソッドなどに移動することにより)。私の精神的プロセスを複製する「メタ」ソリューションを探しています。

「すべての要素がクラス名になることはわかっています。すべての XML 属性はフィールド名になることもわかっています。割り当てるコードは @#{attribute_name} = el.[#{attribute_name} ] そして、サブ要素に再帰します。そして、to_xml を逆にします。"


「ビルダー」クラスと XmlSimple が正しい道のように思われるという提案に同意します。XML -> ハッシュ -> ? -> オブジェクト モデル (そして利益!)


更新 2008-09-18 AM: @Roman、@fatgeekuk、@ScottKoon からの優れた提案により、問題が解決したようです。HPricot のソースをダウンロードして、問題がどのように解決されたかを確認しました。重要なメソッドは明らかに instance_variable_set と class_eval です。irb の作業は非常に心強いものであり、現在実装に向けて動いています....非常に興奮しています

4

5 に答える 5

1

to_xml メソッドを作成する代わりに Builder を使用できます。また、 from _xml メソッドを使用する代わりに、XMLSimple を使用して xml ファイルをハッシュにプルできます。残念ながら、これらのテクニックを使って本当に多くのことが得られるかどうかはわかりません。

于 2008-09-17T20:12:58.473 に答える
1

最初に XmlSimple を使用することをお勧めします。入力ファイルで XmlSimple#xml_in を実行すると、ハッシュが取得されます。次に、(obj.instance_variables) に再帰して、すべての内部ハッシュ (element.is_a?(Hash)) を同じ名前のオブジェクトに変換できます。次に例を示します。

obj.instance_variables.find {|v| obj.send(v.gsub(/^@/,'').to_sym).is_a?(Hash)}.each do |h|
  klass= eval(h.sub(/^@(.)/) { $1.upcase })

おそらく、これを行うためのよりクリーンな方法を見つけることができます。その後、この新しいオブジェクトから xml を作成する場合は、おそらく XmlSimple#xml_out を変更して別のオプションを受け入れる必要があります。これにより、オブジェクトが引数として受け取るために使用される通常のハッシュと区別されます。 XmlSimple#value_to_xml メソッドのバージョンを記述する必要があるため、ハッシュ構造にアクセスしようとする代わりに、アクセサー メソッドを呼び出します。もう 1 つのオプションは、必要なインスタンス変数を返すことによって、すべてのクラスで [] 演算子をサポートすることです。

于 2008-09-18T12:25:09.450 に答える
0

attr_accessor をサブクラス化して、to_xml と from_xml を作成します。

このようなもの(注、これは完全に機能するわけではなく、概要のみです)

class XmlFoo
  def self.attr_accessor attributes = {}
    # need to add code here to maintain a list of the fields for the subclass, to be used in to_xml and from_xml
    attributes.each do |name, value|
      super name
    end
  end

  def to_xml options={}
    # need to use the hash of elements, and determine how to handle them by whether they are .kind_of?(XmlFoo)
  end

  def from_xml el
  end
end

あなたはそれを次のように使うことができます....

class Second < XmlFoo
  attr_accessor :first_attr => String, :second_attr => Float
end

class First < XmlFoo
  attr_accessor :normal_attribute => String, :sub_element => Second
end

これが一般的な考えを与えることを願っています。

于 2008-09-18T11:08:35.030 に答える
0

hpricotを使用して XML を解析し、出力を使用して単純な古い Ruby オブジェクトを構築してみてください。【免責事項】私はこれを試していません。

于 2008-09-18T05:46:03.527 に答える
0

次のことができるメソッドが見つからないことを定義できますか:

@bar = el.bar? それはいくつかのボイラープレートを取り除くでしょう。Bat が常にそのように定義される場合は、XPath を initialize メソッドにプッシュできます。

class Bar
  def initialize(el)
    self.from_xml(XPath.first(el, "./bat"))
  end
end

Hpricot や REXML も役立つかもしれません。

于 2008-09-17T20:07:22.340 に答える