如何从XML获取属性

时间:2017-05-08 21:30:07

标签: ruby xml nokogiri

我有一个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)

1 个答案:

答案 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使用|分隔。

但是,对于XPath,

xn:SubNetwork不正确,因为您需要告诉Nokogiri在文档中查找的位置。 //表示在XPath-ese中“搜索无处不在”,并允许Nokogiri确定它应该使用XPath:

doc.at('//xn:SubNetwork', namespaces)['id'] # => "ONRM_ROOT_MO_R"

在“搜索XML / HTML文档”教程中,在页面末尾阅读Nokogiri的“Namespaces”文档以及collect_namespaces文档。