我有这个XML:
<Experiment>
<mzData version="1.05" accessionNumber="1635">
<description>
<admin>
<sampleName>Fas-induced and control Jurkat T-lymphocytes</sampleName>
<sampleDescription>
<cvParam cvLabel="MeSH" accession="D017209" name="apoptosis" />
<cvParam cvLabel="UNITY" accession="D2135" name="Jurkat cells" />
<cvParam cvLabel="MeSH" accession="D019014" name="Antigens, CD95" />
</sampleDescription>
</admin>
</description>
</mzData>
</Experiment>
</ExperimentCollection>
我还有以下代码:
require 'rubygems'
require 'nokogiri'
doc = Nokogiri::XML(File.open("my.xml"))
sampleName = doc.xpath( "/ExperimentCollection/Experiment/mzData/description/admin/sampleName" ).text
sampleDescription = doc.xpath( "/ExperimentCollection/Experiment/mzData/description/admin/sampleDescription/MeSH/@accession" ).text
puts sampleName + " " + sampleDescription
foo = sampleName + " " + sampleDescription
f = File.new("my.txt","w")
f.write(foo)
f.close()
代码抓住sampleName
就好了,但不是accession
字母/数字。我只想抓住MeSH
- &gt;之后的所有字母/数字。 accession
(D017209
和D019014
)。我需要在doc.xpath
命令中进行哪些更改才能使其正常工作?
答案 0 :(得分:2)
doc.xpath( "/ExperimentCollection/Experiment/mzData/description/admin/sampleDescription/MeSH/@accession" )
不返回任何内容,因为没有标记MeSH
。您需要将MeSH
替换为cvParam[@cvLabel=\"MeSH\"]
(读取:cvParam
标记,其属性cvLabel
的值为MeSH
。)
修复后,xpath
将返回Nokogiri::XML::Attr
个对象的集合。通过调用该集合上的文本,您将获得第一个元素的字符串值。既然你想要所有的元素,你应该使用map(&:text)
(或ruby 1.8.6中的map {|n| n.text}
),这将返回一个包含每个accession
属性的字符串值的数组(即{{ 1}}用于示例XML文件。)
既然你似乎感到困惑,这里有一个澄清:
@Bobby:当我说“["D017209", "D019014"]
将返回xpath
个对象的集合”时,我的意思就是这样。您调用Nokogiri::XML::Attr
然后xpath
创建并返回xpath
个对象的集合。我绝不意味着您应该自己手动创建任何Attr
个对象。
当我说你应该使用Attr
时,我的意思是你应该在map
返回的集合上调用map
(尽管你可以只使用xpath
而不是map
以集合作为参数调用puts
。
xpath
和固定的xpath来获取集合换句话说:
require 'rubygems'
require 'nokogiri'
doc = Nokogiri::XML(File.open("my.xml"))
common_prefix = "/ExperimentCollection/Experiment/mzData/description/admin"
sample_name = doc.xpath( common_prefix+"/sampleName" ).text
accessions = doc.xpath( common_prefix+
"/sampleDescription/cvParam[@cvLabel=\"MeSH\"]/@accession" )
puts sample_name
puts accessions
答案 1 :(得分:0)
这是一种简单的方法,虽然这可能太聪明了,因为你可能也想做其他事情:
File.open("my.txt","w") do |f|
doc.xpath('//cvParam[@cvLabel="MeSH"]').each {|n| f << "#{n['name']} #{n['accession']}\n"}
end
您可能需要更具选择性的xpath语句。