我有多个XML(如下所示),其中显示可选标记。此标记位于名称空间mynamespace
xml = %{<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:mynamespace="http://example.com/ns/1.0">
<channel>
<item>
<title>bar</title>
<mynamespace:custom_tag>some text</mynamespace:custom_tag>
</item>
<item>
<title>foo</title>
</item>
</channel>
</rss>}
Nokogiri::XML::Reader(xml).each do |node|
next if node.name!='item' || node.node_type != Nokogiri::XML::Reader::TYPE_ELEMENT
node = Nokogiri::XML.parse(node.outer_xml)
puts "-> node"
puts node.namespaces
puts node.xpath("//mynamespace:custom_tag").text
end
当Nokogiri::XML::Reader(xml)
遍历每个<item>
时,第一次运行会输出some text
。但是当第二个项目(不包含具有mynamespace
命名空间的元素)被解析时,会抛出错误。
输出结果为:
-> node
{"xmlns:mynamespace"=>"http://example.com/ns/1.0"}
some text
-> node
{}
Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: //mynamespace:custom_tag
- 为什么Nokogiri在第一项中包含命名空间而在第二项中没有?只是因为第一个使用命名空间,第二个不使用命名空间
- 搜索带有命名空间的标记的解决方法是什么,即使此命名空间不在当前节点中发生?
答案 0 :(得分:1)
- 为什么Nokogiri在第一项中包含命名空间而在第二项中没有?只是因为第一个使用命名空间,第二个不使用命名空间
醇>
要了解差异,请查看第一个node.outer_xml
的{{1}}返回内容:
<item>
...与第二个:
<item xmlns:mynamespace="http://example.com/ns/1.0">
<title>bar</title>
<mynamespace:custom_tag>some text</mynamespace:custom_tag>
</item>
您会注意到,在第一种情况下,<item>
<title>foo</title>
</item>
与输入XML不同:Nokogiri有用地包含父元素上任何子元素的名称空间声明。在第二种情况下,没有任何元素具有任何名称空间,因此Nokogiri不包含任何名称空间声明。
- 搜索带有命名空间的标记的解决方法是什么,即使此命名空间不在当前节点中发生?
醇>
一个简单的解决方案是使用条件跳过不包含命名空间的元素:
outer_xml
您注意到我还使用Nokogiri::XML::Reader(xml).each do |node|
next unless node.name == 'item' && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
item_doc = Nokogiri::XML.parse(node.outer_xml)
puts "-> node"
unless item_doc.namespaces.key?("xmlns:mynamespace")
puts "Does not include namespace; skipping"
next
end
puts item_doc.xpath("//mynamespace:custom_tag").text
end
# => -> node
# some text
# -> node
# Element doesn't include namespace; skipping
更改了块内的变量名node
,因为item_doc
返回Nokogiri :: XML :: Document,而不是Node,命名很混乱。
更简单的解决方案是使用Nokogiri的内存解析器而不是XML :: Reader:
Nokogiri::XML.parse
您可能正在使用XML :: Reader,因为XML文档很大,但除非您遇到实际内存或性能问题,否则我建议您使用此方法。