2017-08-24 14 views
1

XML文書からノードセットを繰り返し分離して操作しようとしていますが、xml_find_all()関数のxml2パッケージのRで奇妙な動作が発生しています。私はノードセットに適用される機能の範囲を理解していますか?ここでRxml2内の単一のXMLノードセットからデータを分離する

は一例です:

library(xml2) 
library(dplyr) 

doc <- read_xml("<MEMBERS> 
        <CUSTOMER> 
         <ID>178</ID> 
         <FIRST.NAME>Alvaro</FIRST.NAME> 
         <LAST.NAME>Juarez</LAST.NAME> 
         <ADDRESS>123 Park Ave</ADDRESS> 
         <ZIP>57701</ZIP> 
        </CUSTOMER> 
        <CUSTOMER> 
         <ID>934</ID> 
         <FIRST.NAME>Janette</FIRST.NAME> 
         <LAST.NAME>Johnson</LAST.NAME> 
         <ADDRESS>456 Candy Ln</ADDRESS> 
         <ZIP>57701</ZIP> 
        </CUSTOMER> 
        </MEMBERS>" ) 

doc %>% xml_find_all('//*') %>% xml_path() 
# [1] "/MEMBERS"      "/MEMBERS/CUSTOMER[1]"   
# [3] "/MEMBERS/CUSTOMER[1]/ID"   "/MEMBERS/CUSTOMER[1]/FIRST.NAME" 
# [5] "/MEMBERS/CUSTOMER[1]/LAST.NAME" "/MEMBERS/CUSTOMER[1]/ADDRESS" 
# [7] "/MEMBERS/CUSTOMER[1]/ZIP"  "/MEMBERS/CUSTOMER[2]"   
# [9] "/MEMBERS/CUSTOMER[2]/ID"   "/MEMBERS/CUSTOMER[2]/FIRST.NAME" 
#[11] "/MEMBERS/CUSTOMER[2]/LAST.NAME" "/MEMBERS/CUSTOMER[2]/ADDRESS" 
#[13] "/MEMBERS/CUSTOMER[2]/ZIP" 

オブジェクトcustomer.01のみがその顧客からのデータを含むノードセットです。

kids <- xml_children(doc) 

customer.01 <- kids[[1]] 

customer.01 
# {xml_node} 
# <CUSTOMER> 
# [1] <ID>178</ID> 
# [2] <FIRST.NAME>Alvaro</FIRST.NAME> 
# [3] <LAST.NAME>Juarez</LAST.NAME> 
# [4] <ADDRESS>123 Park Ave</ADDRESS> 
# [5] <ZIP>57701</ZIP> 

なぜ、customer.01ノードセットに適用された関数は、customer.02のIDも返しますか?

xml_find_all(customer.01, "//MEMBERS/CUSTOMER/ID") 
# {xml_nodeset (2)} 
# [1] <ID>178</ID> 
# [2] <ID>934</ID> 

ノードセットから値だけを返すにはどうすればよいですか?

~~~

オクラホマので、ここで再度xml_find_all()関数の範囲に関連する以下の溶液中で小さなシワがあります。ドキュメント、ノード、またはノードセットに適用できると言われています。

library(xml2) 
url <- "https://s3.amazonaws.com/irs-form-990/201501279349300635_public.xml" 
doc <- read_xml(url) 
xml_ns_strip(doc) 
nd <- xml_find_all(doc, "//LiquidationOfAssetsDetail|//LiquidationDetail") 

nodei <- nd[[1]] 
nodei 
# {xml_node} 
# <LiquidationOfAssetsDetail> 
# [1] <AssetsDistriOrExpnssPaidDesc>LAND</AssetsDistriOrExpnssPaidDesc> 
# [2] <DistributionDt>2014-11-04</DistributionDt> 
# [3] <MethodOfFMVDeterminationTxt>SEE ATTACH</MethodOfFMVDeterminationTxt> 
# [4] <EIN>abcdefghi</EIN> 
# [5] <BusinessName>\n <BusinessNameLine1Txt>GREENSBURG PUBLIC LIBRARY</BusinessNameLine1Txt>\n</BusinessName> 
# [6] <USAddress>\n <AddressLine1Txt>1110 E MAIN ST</AddressLine1Txt>\n <CityNm>GREENSBURG</CityNm>\n <StateAbbreviationCd>IN</StateAb ... 
# [7] <IRCSectionTxt>501(C)(3)</IRCSectionTxt> 

xml_text(xml_find_all(nodei, "AssetsDistriOrExpnssPaidDesc")) 
# [1] "LAND" 

ではなく、この1:ノードセットに適用されたときしかし...

この場合は動作します

nodei <- xml_children(nd[[i]]) 
nodei 
# {xml_nodeset (7)} 
# [1] <AssetsDistriOrExpnssPaidDesc>LAND</AssetsDistriOrExpnssPaidDesc> 
# [2] <DistributionDt>2014-11-04</DistributionDt> 
# [3] <MethodOfFMVDeterminationTxt>SEE ATTACH</MethodOfFMVDeterminationTxt> 
# [4] <EIN>abcdefghi</EIN> 
# [5] <BusinessName>\n <BusinessNameLine1Txt>GREENSBURG PUBLIC LIBRARY</BusinessNameLine1Txt>\n</BusinessName> 
# [6] <USAddress>\n <AddressLine1Txt>1110 E MAIN ST</AddressLine1Txt>\n <CityNm>GREENSBURG</CityNm>\n <StateAbbreviationCd>IN</StateAb ... 
# [7] <IRCSectionTxt>501(C)(3)</IRCSectionTxt> 

xml_text(xml_find_all(nodei, "AssetsDistriOrExpnssPaidDesc")) 
# character(0) 

私は、これはすべての問題適用xml_find_all()は推測していますスコープの問題ではなく、ノードセットの要素ですか?

答えて

3

現在、あなたは両方の顧客のIDが含まれ、このパスに一致するドキュメント内のすべてののアイテムを見つける意味するXPathのダブルスラッシュ、//、とのルートからの絶対パス検索を使用しています。

特定のノードの下に特定の子ノードの場合、単純に選択したノードの下に相対パスを使用します。

xml_find_all(customer.01, "ID") 
# {xml_nodeset (1)} 
# [1] <ID>178</ID> 

xml_find_all(customer.01, "FIRST.NAME|LAST.NAME") 
# {xml_nodeset (2)} 
# [1] <FIRST.NAME>Alvaro</FIRST.NAME> 
# [2] <LAST.NAME>Juarez</LAST.NAME> 

xml_find_all(customer.01, "*") 
# {xml_nodeset (5)} 
# [1] <ID>178</ID> 
# [2] <FIRST.NAME>Alvaro</FIRST.NAME> 
# [3] <LAST.NAME>Juarez</LAST.NAME> 
# [4] <ADDRESS>123 Park Ave</ADDRESS> 
# [5] <ZIP>57701</ZIP> 
+0

パーフェクト!ありがとうございました! –

+0

素晴らしい!喜んで助けてください。ところで、[Stackoverflowへの感謝](https://meta.stackexchange.com/a/5235)と言う特別な方法があります。 – Parfait

+0

これはまた動作します: 'xml_find_all(customer.01、" // ID ")'これは全てのケースを返します。 しかし、私はあなたの解決策よりも利点があるとは思わない: 'xml_find_all(customer.01、" ID ")' –

関連する問題