0

これは私の単純化された myXML です:

<?xml version="1.0" encoding="utf-8"?>
<ShipmentRequest>
  <Message>
      <MemberId>A00000001</MemberId>
      <MemberName>Bruce</MemberName>
    <Line>
      <LineNumber>3.1</LineNumber>
      <Item>fruit-004</Item>
      <Description>Peach</Description>
    </Line>
    <Line>
      <LineNumber>4.1</LineNumber>
      <Item>fruit-001</Item>
      <Description>Peach</Description>
    </Line>
  </Message>
</ShipmentRequest>

Crack gem で解析すると、次のようになりmyHashます。

{
   "MemberId"=>"A00000001", 
   "MemberName"=>"Bruce", 
   "Line"=>[
       {"LineNumber"=>"3.1", "Item"=>"A0001", "Description"=>"Apple"}, 
       {"LineNumber"=>"4.1", "Item"=>"A0002", "Description"=>"Peach"}
    ]
}

myXML には 2 つのノードがあるため、Crack gem はハッシュLineを配列として作成します。<Line>ただし、myXML に<Line>ノードが 1 つしか含まれていない場合、Crack gem はそれを配列として解析しません。

{
    "MemberId"=>"ABC0001", 
    "MemberName"=>"Alan", 
    "Line"=> {"LineNumber"=>"4.1", "Item"=>"fruit-004", "Description"=>"Apple"}
}

ノードが1つしかない場合でも、配列として表示したい:

{
    "MemberId"=>"ABC0001", 
    "MemberName"=>"Alan", 
    "Line"=> [{"LineNumber"=>"4.1", "Item"=>"fruit-004", "Description"=>"Apple"}]
}
4

2 に答える 2

1

問題は、本当にすべきことをコードに頼っていることです。Crack は、1 つのノードを 1 つの要素の配列にする必要があるとは考えていません。そのため、データのその部分に飛び込もうとすると、その動作が非常に難しくなります。

XML の構文解析は難しくありません。自分で構文解析することで、何を期待すればよいかがわかります。また、Crack によって返される「配列である場合もあれば、そうでない場合もある」という面倒な処理を回避できます。

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="utf-8"?>
<ShipmentRequest>
  <Message>
      <MemberId>A00000001</MemberId>
      <MemberName>Bruce</MemberName>
    <Line>
      <LineNumber>3.1</LineNumber>
      <Item>fruit-004</Item>
      <Description>Peach</Description>
    </Line>
    <Line>
      <LineNumber>4.1</LineNumber>
      <Item>fruit-001</Item>
      <Description>Peach</Description>
    </Line>
  </Message>
</ShipmentRequest>
EOT

これにより DOM がセットアップされ、ナビゲートできるようになります。

hash = {}
message = doc.at('Message')
hash[:member_id] = message.at('MemberId').text
hash[:member_name] = message.at('MemberName').text
lines = message.search('Line').map do |line|
  line_number = line.at('LineNumber').text 
  item = line.at('Item').text 
  description = line.at('Description').text

  {
    :line_number => line_number,
    :item        => item,
    :description => description
  }
end
hash[:lines] = lines
  1. message = doc.at('Message')<Message>最初のノードを見つけます。
  2. message.at('MemberId').text<MemberID>内の最初のノードを見つけます<Message>
  3. message.at('MemberName').text上記の手順に似ています。
  4. message.search('Line')内のすべての<Line>ノードを検索します<Message>

これらの説明から、残りを把握できます。

実行後、hash次のようになります。

{:member_id=>"A00000001",
:member_name=>"Bruce",
:lines=>
  [{:line_number=>"3.1", :item=>"fruit-004", :description=>"Peach"},
  {:line_number=>"4.1", :item=>"fruit-001", :description=>"Peach"}]}

XML からブロックの 1 つを削除<Line>して再実行すると、次のようになります。

{:member_id=>"A00000001",
:member_name=>"Bruce",
:lines=>[{:line_number=>"3.1", :item=>"fruit-004", :description=>"Peach"}]}

を使用searchしてノードを見つけるの<Line>がコツです。searchArray に似た NodeSet を返すため、これを使用して反復処理を行うと、タグmapのコンテンツのハッシュの配列が返されます。<Line>

Nokogiriは、HTML と XML を解析するための優れたツールであり、ノードを検索、追加、変更、または削除できます。CSS および XPath アクセサーをサポートしているため、jQuery や CSS の仕組み、または XPath 式に慣れている場合は、すぐに使い始めることができます。Nokogiri のチュートリアルは、それがどのように機能するかを学ぶための良い出発点です。

于 2013-06-09T05:15:46.163 に答える