从R xml2中的单个XML节点集隔离数据

时间:2017-08-24 16:12:46

标签: r xml xml2

我试图从XML文档迭代地隔离和操作节点集,但是我在R的xml2包中的xml_find_all()函数中得到一个奇怪的行为。有人可以帮我理解应用于a的函数的范围节点集?

以下是一个例子:

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 nodeset的函数也会返回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"

但不是这一个:

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()应用于节点集的所有元素而不是范围问题的问题?

1 个答案:

答案 0 :(得分:3)

目前,您正在使用来自root的绝对路径搜索和XPath的双正斜杠//,这意味着在文档中找到与该路径匹配的所有项目,其中包括两个客户&#39; ID。

对于特定节点下的特定子节点,只需在所选节点下使用相对路径:

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>