我有一个XML文件,如:
<?xml version="1.0" encoding="UTF-8"?>
<bulkCmConfigDataFile xmlns:es="EricssonSpecificAttributes.17.08.xsd"
xmlns:un="utranNrm.xsd" xmlns:xn="genericNrm.xsd"
xmlns:gn="geranNrm.xsd" xmlns="configData.xsd">
<fileHeader fileFormatVersion="32.615 V4.5" vendorName="Ericsson"/>
<configData dnPrefix="Undefined">
<xn:SubNetwork id="ONRM_ROOT_MO_R">
<xn:SubNetwork id="MKT_9364">
<xn:MeContext id="936426_SEYMOUR">
</xn:MeContext>
</xn:SubNetwork>
</xn:SubNetwork>
</configData>
<fileFooter dateTime="2017-05-08T10:15:53Z"/>
</bulkCmConfigDataFile>
我想从文件中获取所有属性。我可以获得@doc.at('fileHeader')['vendorName']
,但我没有收到第二个ONRM_ROOT_MO_R
声明的预期结果puts
。
这是我的Ruby代码:
#!/usr/bin/env ruby
require 'xmlsimple'
require 'nokogiri'
require 'ap'
@doc = Nokogiri::XML(File.open("seymour.xml"))
puts @doc.at('fileHeader')['vendorName']
puts @doc.at('xn:SubNetwork')['id']
输出结果为:
Ericsson
./bulk_cm_parse.rb:10:in `<main>': undefined method `[]' for nil:NilClass
(NoMethodError)
答案 0 :(得分:-1)
您的文档有名称空间,因此您必须考虑这些名称,加上您的选择器错误:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="UTF-8"?>
<bulkCmConfigDataFile xmlns:es="EricssonSpecificAttributes.17.08.xsd"
xmlns:un="utranNrm.xsd" xmlns:xn="genericNrm.xsd"
xmlns:gn="geranNrm.xsd" xmlns="configData.xsd">
<fileHeader fileFormatVersion="32.615 V4.5" vendorName="Ericsson"/>
<configData dnPrefix="Undefined">
<xn:SubNetwork id="ONRM_ROOT_MO_R">
<xn:SubNetwork id="MKT_9364">
<xn:MeContext id="936426_SEYMOUR">
</xn:MeContext>
</xn:SubNetwork>
</xn:SubNetwork>
</configData>
<fileFooter dateTime="2017-05-08T10:15:53Z"/>
</bulkCmConfigDataFile>
EOT
namespaces = doc.collect_namespaces
doc.at('xn|SubNetwork', namespaces)['id'] # => "ONRM_ROOT_MO_R"
at
,与search
一样,试图弄清楚您是使用CSS选择器还是XPath。你的选择器没有正常的XPath标记,所以它假设你的意思是CSS,但是后来命名空间没有正确地为CSS使用|
分隔。
xn:SubNetwork
不正确,因为您需要告诉Nokogiri在文档中查找的位置。 //
表示在XPath-ese中“搜索无处不在”,并允许Nokogiri确定它应该使用XPath:
doc.at('//xn:SubNetwork', namespaces)['id'] # => "ONRM_ROOT_MO_R"
在“搜索XML / HTML文档”教程中,在页面末尾阅读Nokogiri的“Namespaces”文档以及collect_namespaces
文档。