0

Nokogiri を使用して、(大まかに) 次の構造を持つ XML ファイルを解析しています。

<diag>
  <name>A00</name>
  <desc>Cholera</desc>
  <diag>
    <name>A00.0</name>
    <desc>Cholera due to Vibrio cholerae 01, biovar cholerae</desc>
  </diag>
  <diag>
    ...
  </diag>
  ...
</diag>

ご覧のとおり、このツリーにはdiag任意の深さでネストできるノードがありますが、各ネストは親ノードのより具体的な説明です。

このツリーを「平坦化」して、A00.0ネストするのではなく、A00次のようなリストを作成したい

A00
A00.0
A00.1
...
A00.34
...
A01
...

私がこれまでに持っているものは次のようになります。

require 'nokogiri'
icd10 = File.new("icd10.xml", "r")
doc = Nokogiri::XML(icd10.read) do |config|
  config.strict.noblanks
end
icd10.close

@diags = {}
@diag_count = 0

def get_diags(node)
  node.children.each do |n|
    if n.name == "diag"
      @diags[@diag_count] = n
      @diag_count += 1
      get_diags(n)
    end
  end
end

# The xml file has sections but what I really want are the contents of the sections
doc.xpath('.//section').each do |n|
  get_diags(n)
end

これまでのところ、これdiagはファイル内のすべての要素を取得するという点で機能しますが、問題は、親ノードに後のノードで見つかったすべてのコンテンツが含まれていることです (たとえば、、、 などのノードが@diags[0]含まれ、コンテンツのみが含まれています)。 )。A00A00.0A00.1@diags[1]A00.0

でxmlコンテンツをトラバースするときに、親要素からネストされた要素を除外するにはどうすればよいget_diagsですか? 前もって感謝します!

==編集==

だから私は私のget_diags方法にこれを追加しました

def get_diags(node)
  node.children.each do |n|
    if n.name == "diag"
      f = Nokogiri::XML.fragment(n.to_s)
      f.search('.//diag').children.each do |d|
        if d.name == "diag"
          d.remove
        end
      end
      @diags[@diag_count] = f
      @diag_count += 1
      get_diags(n)
    end
  end
end

@diags入れ子になったものがすべて削除された xml のフラグメントを保持するようになりまし<diag>...</diag>た。これはある意味では私が望んでいるものですが、全体的にこれは非常に見苦しく、誰かがこれを行うためのより良い方法を共有できるかどうか疑問に思っていました。ありがとう

4

1 に答える 1

2

xpath '//diag' は<diag>、ネストの深さに関係なく、順番に各ノードを提供します。次に、各ノードのnamedescの子のテキスト値を抽出するだけです。

diags = doc.xpath('//diag').map do |diag|
  Hash[
    %w(name desc).map do |key|
      [key, diag.xpath(key).text]
    end
  ]
end
pp diags
# => [{"desc"=>"Cholera", "name"=>"A00"},
# =>  {"desc"=>"Cholera due to Vibrio cholerae 01, biovar cholerae",
# =>   "name"=>"A00.0"}]

別の構造を持つ新しい XML ツリーを作成したい場合は、わざわざオリジナルを変換しようとはしません。抽出されたデータを取得し、それを使用して新しいツリーを作成するだけです。

builder = Nokogiri::XML::Builder.new do |xml|
  xml.diagnoses do
  diags.each do |diag|
    xml.diag {
      xml.name = diag['name']
      xml.desc = diag['desc']
    }
  end
  end
end
puts builder.to_xml
# => <?xml version="1.0"?>
# => <diagnoses>
# =>   <diag>
# =>     <name=>A00</name=>
# =>     <desc=>Cholera</desc=>
# =>   </diag>
# =>   <diag>
# =>     <name=>A00.0</name=>
# =>     <desc=>Cholera due to Vibrio cholerae 01, biovar cholerae</desc=>
# =>   </diag>
# => </diagnoses>
于 2012-06-27T17:29:13.263 に答える