如何从 XML 获取属性

How to fetch attributes from XML

我有一个 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'] 但我没有得到第二个 puts 语句的预期结果 ONRM_ROOT_MO_R

这是我的 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)

您的文档有命名空间,因此您必须考虑到这些,而且您的选择器有误:

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 对于 XPath 也不正确,因为您需要告诉 Nokogiri 在文档中查找的位置。 // 在 XPath-ese 中表示 "search everywhere" 并允许 Nokogiri 确定它应该使用 XPath:

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

阅读 Nokogiri 的“Namespaces" documentation in the "Searching a XML/HTML Document" tutorial, to the end of the page, along with the collect_namespaces 文档。