如何从 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
文档。
我有一个 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
文档。