2016-06-30 12 views
0

I次の例のドキュメントがあります。他のタグに基づいてタグからデータを取得する方法

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<n1:Form109495CTransmittalUpstream xmlns="urn:us:gov:treasury:irs:ext:aca:air:7.0" xmlns:irs="urn:us:gov:treasury:irs:common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:us:gov:treasury:irs:msg:form1094-1095Ctransmitterupstreammessage IRS-Form1094-1095CTransmitterUpstreamMessage.xsd" xmlns:n1="urn:us:gov:treasury:irs:msg:form1094-1095Ctransmitterupstreammessage"> 
<Form1095CUpstreamDetail RecordType="String" lineNum="1"> 
<RecordId>1</RecordId> 
<CorrectedInd>0</CorrectedInd> 
<irs:TaxYr>2015</irs:TaxYr> 
<EmployeeInfoGrp> 
<OtherCompletePersonName> 
<PersonFirstNm>JOHN</PersonFirstNm> 
<PersonMiddleNm>B</PersonMiddleNm> 
<PersonLastNm>Doe</PersonLastNm> 
</OtherCompletePersonName> 
<PersonNameControlTxt/> 
<irs:TINRequestTypeCd>INDIVIDUAL_TIN</irs:TINRequestTypeCd> 
<irs:SSN>123456790</irs:SSN> 
</Form1095CUpstreamDetail> 
<Form1095CUpstreamDetail RecordType="String" lineNum="1"> 
<RecordId>2</RecordId> 
<CorrectedInd>0</CorrectedInd> 
<irs:TaxYr>2015</irs:TaxYr> 
<EmployeeInfoGrp> 
<OtherCompletePersonName> 
<PersonFirstNm>JANE</PersonFirstNm> 
<PersonMiddleNm>B</PersonMiddleNm> 
<PersonLastNm>DOE</PersonLastNm> 
</OtherCompletePersonName> 
<PersonNameControlTxt/> 
<irs:TINRequestTypeCd>INDIVIDUAL_TIN</irs:TINRequestTypeCd> 
<irs:SSN>222222222</irs:SSN> 
</EmployeeInfoGrp> 
</Form1095CUpstreamDetail> 
</n1:Form109495CTransmittalUpstream> 

私は<RecordId>に基づいて、各<Form1095CUpstreamDetail>について<PersonFirstNm><PersonLastNm><irs:SSN>の間の値を抽出したい鋸山を使用します。

名前空間も削除しようとしました。私は小さなスニペットを投稿しましたが、私はXMLを成功させるために何度も試してみました。これは初めてXMLを使用しているので、簡単に何かを見逃している可能性があります。私は上記のRecordIdとタグの間の任意の関連を持っていないように見えます

require 'nokogiri' 
submission_doc = Nokogiri::XML(open('1094C_Request.xml')) 
submissions = submission_doc.remove_namespaces 
nodes = submission.xpath('//Form1095CUpstreamDetail') 

、と私は次の行くところに貼り付けています:私は私のXPathを設定

フィールドはRecordIdの子としてリストされていないので、値を取得する方法を考えることはできません。私は何かを排除していないことを確認するための例として完全な文書を含めています。

私は値の配列を持っています。RecordIdが数値の配列に含まれている場合は、上記の3つのタグを取りたいと思います。

+1

「[mcve]」を読んでから、入力XMLを問題を実証するために必要な最小限の絶対量に減らしてください。それ以外のものは、私たちの時間を浪費するだけです。また、テキスト内の変数の書式設定に時間を費やしてください。それは、助けを求める人や、将来類似の解決策を探している人たちに、その質問を理解させるのに役立ちます。 –

+0

XMLが無効です。解析に問題が発生する可能性があります。不一致のタグは、パーサーに回復を試み、何か有用なものを提供しようとすると、パーサーにフィックスアップを強制しますが、そのプロセスはタグが失われる原因となります。コードを適切な出発点にするためには、XMLを解析する前にXMLを修正する方法を理解する必要があります。 Nokogiri 'submission_doc.errors'は、解析後に「開始タグと終了タグの不一致:Form1094CUpstreamDetail 3行目とForm1095CUpstreamDetail」を返します。 –

+0

ありがとうございました@theTinMan私はそれらのエラーにもっと注意を払う必要がありました、それはソースがそれらを提供し、私のXMLの問題を引き起こす前にファイルを操作していたことが判明。 私は上記の情報を利用して、あなたの要求に応えようと努力しました。 頭痛や問題の原因となった教訓と謝罪。 – StoutPanda

答えて

0

に役立ちます願っています。

require 'nokogiri' 
require 'pp' 

doc = Nokogiri::XML(<<EOT) 
<n1:Form109495CTransmittalUpstream xmlns="urn:us:gov:treasury:irs:ext:aca:air:7.0" xmlns:irs="urn:us:gov:treasury:irs:common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:us:gov:treasury:irs:msg:form1094-1095Ctransmitterupstreammessage IRS-Form1094-1095CTransmitterUpstreamMessage.xsd" xmlns:n1="urn:us:gov:treasury:irs:msg:form1094-1095Ctransmitterupstreammessage"> 
    <Form1095CUpstreamDetail RecordType="String" lineNum="1"> 
    <RecordId>1</RecordId> 
    <PersonFirstNm>JOHN</PersonFirstNm> 
    <PersonLastNm>Doe</PersonLastNm> 
    <irs:SSN>123456790</irs:SSN> 
    </Form1095CUpstreamDetail> 
    <Form1095CUpstreamDetail RecordType="String" lineNum="1"> 
    <RecordId>2</RecordId> 
    <PersonFirstNm>JANE</PersonFirstNm> 
    <PersonLastNm>DOE</PersonLastNm> 
    <irs:SSN>222222222</irs:SSN> 
    </Form1095CUpstreamDetail> 
</Form109495CTransmittalUpstream> 
EOT 

info = doc.search('Form1095CUpstreamDetail').map{ |form| 
    { 
    record_id:  form.at('RecordId').text, 
    person_first_nm: form.at('PersonFirstNm').text, 
    person_last_nm: form.at('PersonLastNm').text, 
    ssn:    form.at('irs|SSN').text 
    } 
} 
pp info 
# >> [{:record_id=>"1", 
# >> :person_first_nm=>"JOHN", 
# >> :person_last_nm=>"Doe", 
# >> :ssn=>"123456790"}, 
# >> {:record_id=>"2", 
# >> :person_first_nm=>"JANE", 
# >> :person_last_nm=>"DOE", 
# >> :ssn=>"222222222"}] 

それは、XPathでこれを行うことは可能ですが、CSSセレクタの鋸山の実装は非常に良いことである、維持するために簡単に変換され、セレクタを読みやすくをもたらす傾向:のように私が何かをしたいです。

'irs|SSN'には|が使用されています。これはNokogiriのCSSの名前空間を定義する方法です。これは "Namespaces"に記載されています。

+0

ありがとうございます。ソースに戻り、固定xmlを取得した後、これは簡単に拡張されたより読みやすいスクリプトを提供しました。 – StoutPanda

0

すべてのXMLバリレポートエラーの最初の

デフォルトのXPathクエリの(接頭辞)名前空間URIは、いつもではない 'とそれが再定義することはできません「壷:私たち:GOV:財務省:IRS: ext:aca:air:7.0 '。

このデフォルトのxmlnsを ""に設定する必要があります。

このコードを使用できます。

require 'nokogiri' 

doc = Nokogiri::XML(open('1094C_Request.xml')) 

doc.namespaces['xmlns'] = '' 

details = doc.xpath("//:Form1095CUpstreamDetail") 

elem_a = ["PersonFirstNm", "PersonLastNm", "irs:SSN"] 

output = details.each_with_object({}) do |element, exp| 
    exp[element.xpath("./:RecordId").text] = elem_a.each_with_object({}) do |elem_n, exp_h| 
    exp_h[elem_n] = element.xpath(".//#{elem_n.include?(':') ? elem_n : ":#{elem_n}"}").text 
    end 
end 

出力

p output 
# { 
# "1" => {"PersonFirstNm" => "JOHN", "PersonLastNm" => "Doe", "irs:SSN" => "123456790"}, 
# "2" => {"PersonFirstNm" => "JANE", "PersonLastNm" => "DOE", "irs:SSN" => "222222222"} 
# } 

私は、これは(XMLを仮定すると、構文的に正しい)鋸山はあなたがやりたいことがかなり容易になります

+0

ありがとうございました。これは、私が必要な場所に正確に私を得た。 – StoutPanda

関連する問題