2011-04-01 86 views
0

我正在尝试解析Spotify查找寄存器,但经过多次尝试后,我试图在这里作为最后的手段。使用XPath时遇到问题

相关XML: http://ws.spotify.com/lookup/1/?uri=http://open.spotify.com/track/3aKJVWH2QOsaMtiCLxYHZX

相关代码:

var response = streamReader.ReadToEnd(); 
xml.LoadXml(response); 
var name = xml.SelectSingleNode("//track/name").InnerText; 
var artist = xml.SelectSingleNode("//track/artist/name").InnerText; 
var album = xml.SelectSingleNode("//track/album/name").InnerText; 
var length = xml.SelectSingleNode("//track/length").InnerText; 

相关调试:http://screencast.com/t/yDc8f7Wyzv9P

+0

我已经调试实际的XML内容,所以我知道他们存在的事实。 – miceiken 2011-04-01 23:04:34

+0

你会得到什么错误? – dkackman 2011-04-01 23:04:53

+0

没有,除了变量保持为空,因为它可能根本找不到路径中的元素。 – miceiken 2011-04-01 23:07:23

回答

3

我的猜测是,你应该前缀你的XPath表达式,或者ommit默认命名空间:

http://msdn.microsoft.com/en-us/library/h0hw012b.aspx#Y1372

状态:

注 如果XPath表达式不包含前缀,则假定命名空间URI是空的命名空间。如果您的XML包含默认名称空间,则仍然必须向XmlNamespaceManager添加前缀和名称空间URI;否则,你不会选择一个节点。有关更多信息,请参阅使用XPath导航选择节点。

以下的例子:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); 
nsmgr.AddNamespace("ns", "http://http://www.spotify.com/ns/music/1"); 
var name = xml.SelectSingleNode("//ns:track/ns:name", nsmgr); 
+0

现在,我已经尝试过了,但无论如何我还是给了它另一个镜头,它并没有变好:[链接](http://pastebin.com/K8MPJBWm) – miceiken 2011-04-01 23:20:36

+0

您应该仍然添加命名空间(第二个词组)并在xpath中使用nampespace(第3句) – Peter 2011-04-01 23:25:22

+0

嗯,谢谢,但更新后的示例没有工作, – miceiken 2011-04-01 23:26:33

0

答曰the documentation

如果XPath表达式不包含前缀,则假定命名空间URI是空的命名空间。如果您的XML包含默认名称空间,则仍然必须向XmlNamespaceManager添加前缀和名称空间URI;否则,你不会选择任何节点。

XML文档确实有一个默认名称空间,特别是http://www.spotify.com/ns/music/1。您需要为您的xpath查询提供前缀和名称空间URI。

+0

谢谢,但在我的评论看上面的,它没似乎没有工作,这是尝试添加命名空间:[链接](http://pastebin.com/dB0iGyGJ),我认为我的XPath可能有问题 – miceiken 2011-04-01 23:23:32

+0

@miceiken:您不能使用空的名称空间有关xpath,请参阅[文档](http://msdn.microsoft.com/zh-cn/library/system.xml.xmlnamespacemanager.addnamespace.aspx)。你必须指定在'AddNamespace'呼叫的前缀,然后使用该前缀您的XPath表达式(例如'// ns:对曲目/ NS:name')。 – Anomie 2011-04-01 23:26:55

+0

现在,我也尝试过。我只是觉得它很奇怪,看到值真的存在http://screencast.com/t/yDc8f7Wyzv9P – miceiken 2011-04-01 23:30:03

1

这是一个常见问题:您需要在XPath表达式

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); 
nsmgr.AddNamespace("ns", "http://www.spotify.com/ns/music/1"); 
var name = xml.SelectSingleNode("/ns:track/ns:name", nsmgr); 

另外请注意,没有必要为起始//操作时,日模式是众所周知的注册命名空间的使用它。

+0

没有任何工作。 – miceiken 2011-04-02 19:44:24

+0

@miceiken:你的[代码示例](http://pastebin.com/34zv5av4)具有错误的命名空间URI。仔细阅读我的答案。 – 2011-04-02 20:26:30

0

为什么不使用LINQ to XML让你的生活更轻松?

0

决定尝试另一种方法,这要归功于Windcape我发现XmlSerializer的

var serializer = new XmlSerializer(typeof(Track)); 
var track = (Track)serializer.Deserialize(streamReader); 

var time = TimeSpan.FromSeconds(track.length); 

var ircResponse = string.Format("{0} - {1} ({2}) | {3}min {4}sec | {5}% popular", 
    track.artist.name, 
    track.name, 
    track.album.name, 
    time.TotalMinutes, time.Seconds, 
    Math.Round(track.popularity * 100, 0)); 

CommandHandler.Msg(chan, ircResponse); 
+0

该“办法”是一个很大的不仅仅是选择所需的节点更低效 - 因为它执行完整的XML文档的全面分析,并在另外构造一个完整的新的对象出来。量级更多的订单工作! – 2011-04-03 16:12:54