关于R语言xml2包xml_find_all与xml_find_first函数的疑问
问题:xml2包中xml_find_first/xml_find_all无法匹配带命名空间的XML节点?
在无命名空间的XML中,使用xml_find_first()和xml_find_all()可以正常匹配节点:
library(xml2) x <- read_xml("<foo><bar><baz/></bar><baz/></foo>") xml_find_all(x, ".//baz") xml_find_all(x, ".//bar") xml_find_first(x, ".//bar")
但遇到包含默认命名空间的生产环境XML时,所有匹配调用均返回缺失节点:
library(xml2) yy <- read_xml( '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> <fileVersion appName="xl" lastEdited="3" lowestEdited="5" rupBuild="9302"/> <workbookPr/> <workbookProtection/> <bookViews> <workbookView windowWidth="27090" windowHeight="8700" tabRatio="500" activeTab="1"/> </bookViews> <sheets> <sheet name="PARTICIPANTES" sheetId="1" r:id="rId1"/> <sheet name="ORDENADOS" sheetId="2" r:id="rId2"/> </sheets> <calcPr calcId="144525"/> </workbook>' ) xml_find_first(yy, ".//sheets") xml_find_first(yy, "//sheets") xml_find_all(yy, "//sheets")
错误输出:
{xml_missing} <NA> {xml_missing} <NA> {xml_nodeset (0)}
解决方法
问题出在你的XML定义了默认命名空间(xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"),XPath查询时不会自动识别默认命名空间下的节点,必须显式处理命名空间,有两种常用方案:
方案1:显式绑定命名空间前缀查询
使用xml_ns()获取XML的命名空间信息,然后在XPath表达式中通过前缀指定节点所属的命名空间:
# 获取XML的命名空间集合 ns <- xml_ns(yy) # 使用自动生成的默认前缀(通常为d1)查询节点 xml_find_first(yy, ".//d1:sheets", ns = ns) xml_find_all(yy, "//d1:sheets", ns = ns) # 也可以自定义命名空间前缀,提升可读性 custom_ns <- xml_ns_rename(ns, d1 = "spreadsheet") xml_find_first(yy, ".//spreadsheet:sheets", ns = custom_ns)
方案2:忽略命名空间的XPath写法
如果不需要区分不同命名空间的节点,可使用XPath的local-name()函数匹配节点的本地名称,忽略命名空间限制:
# 匹配所有本地名称为sheets的节点 xml_find_first(yy, ".//*[local-name()='sheets']") xml_find_all(yy, "//*[local-name()='sheets']")
注意:方案1更规范,适合存在多命名空间的复杂XML场景;方案2简单直接,适合仅需匹配节点名称的场景。
内容的提问来源于stack exchange,提问作者JulioSergio
相关产品推荐
相关产品推荐

