使用Nokogiri解析XML时如何忽略未定义的命名空间
Nokogiri处理未定义命名空间的解决方案
Nokogiri原生支持忽略命名空间的相关配置,针对你的场景有两种常用处理方案:
方案1:移除文档所有命名空间(推荐,改动最小)
调用remove_namespaces!方法可以直接清除文档内所有命名空间前缀,不需要修改XML内容,后续XPath查询直接使用节点名即可,修改后的示例代码如下:
require 'nokogiri' def getxml xml_str = <<EOF <root> <THING1:things type="Container"> <PART1:Id type="Property">1234</PART1:Id> <PART1:Name type="Property">The Name1</PART1:Name> </THING1:things> <THING2:things type="Container"> <PART2:Id type="Property">2234</PART2:Id> <PART2:Name type="Property">The Name2</PART2:Name> </THING2:things> </root> EOF doc = Nokogiri::XML(xml_str) # 新增这一行清除所有命名空间 doc.remove_namespaces! doc.xpath('//Id').each do |thing| puts("ID = " + thing.content) puts("Name = " + thing.xpath('./following-sibling::*[local-name()="Name"]')[0].content) end end getxml()
运行后即可正常输出两个Id和对应Name的内容,不会再报命名空间未定义的错误。
方案2:不修改文档结构,XPath匹配本地节点名
如果你需要保留命名空间信息不希望删除,可以在XPath查询时通过local-name()匹配节点的实际名称,忽略前缀限制,同时可以在解析时添加参数屏蔽命名空间报错,示例如下:
# 解析时添加noerror配置屏蔽错误输出 doc = Nokogiri::XML(xml_str) { |config| config.noerror } # XPath使用local-name匹配节点 doc.xpath("//*[local-name()='Id']").each do |thing| puts thing.content end
内容的提问来源于stack exchange,提问作者Tommie Jones
相关产品推荐
相关产品推荐

