使用Nokogiri从这个XML提要中获取“LyricArtist”需要什么?

时间:2010-06-13 20:27:18

标签: ruby xml xpath nokogiri

首先是xml: http://api.chartlyrics.com/apiv1.asmx//GetLyric?lyricId=90&lyricCheckSum=9600c891e35f602eb6e1605fb7b5229e

doc = Nokogiri::XML(open("http://api.chartlyrics.com/apiv1.asmx//GetLyric?lyricId=90&lyricCheckSum=9600c891e35f602eb6e1605fb7b5229e"))

成功获取文档内容。

在此之后我无法进入并抓取数据,我不知道为什么?

例如,我希望:

doc.xpath("//LyricArtist")

要反击艺术家,但事实并非如此。

我尝试过与其他Feed相同的内容,例如任何wordpress安装提供的默认RSS Feed,如果我执行类似的操作:

doc.xpath("//link")

我得到了所有“链接”的列表。

我肯定错过了一些东西,并且非常喜欢你的意见。谢谢!!

2 个答案:

答案 0 :(得分:3)

XML元素是名称空间限定的并绑定到http://api.chartlyrics.com/

如果您查看XML,您会注意到document元素有一个名称空间decalred:

<GetLyricResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://api.chartlyrics.com/">

为了匹配绑定到命名空间的元素,您需要声明绑定到该URI的命名空间前缀并在XPATH表达式中使用该命名空间前缀,或者使用忽略命名空间的XPATH表达式或匹配不同。

您可以匹配元素,然后使用local-name()匹配元素名称,无论声明的名称空间如何。

//*[local-name()='LyricArtist']

如果您想更精确,可以使用local-name()匹配元素名称和namespace-uri()以匹配声明的命名空间。

//*[local-name()='LyricArtist' and namespace-uri()='http://api.chartlyrics.com/']

第二个示例将阻止匹配具有绑定到不同命名空间的相同local-name()的元素。对于这个特定的实例,可能不是问题,但是你应该注意这一点。命名空间用于唯一限定节点,并允许不同的词汇表使用相同的“名称”,而不必担心冲突。

答案 1 :(得分:0)

它不喜欢命名空间或架构中的某些内容。

uri = "http://api.chartlyrics.com/apiv1.asmx//GetLyric?LyricId=90&lyricCheckSum=9600c891e35f602eb6e1605fb7b5229e"
x = open(uri).read()
x = x.sub(/<.*?>/,'').sub(/<.*?>/,'<GetLyricResult>')
doc = Nokogiri::XML(x)
puts doc.xpath('//LyricArtist').text()