在VB中读取XML

时间:2014-08-24 06:41:06

标签: c# xml vb.net itunes

我想在我的应用程序中阅读iTunes Music Library XML但是我不知道如何做到这一点,我想要做的是搜索特定的曲目名称作为一个指定键,例如“艺术家” “,”相册“等等。是的,我知道如何使用iTunes COM,但有一些无法通过它访问的曲目信息,例如如果曲目是”明确“,则有一个额外的密钥

<key>Explicit</key><true/>

我想要做的是搜索特定的曲目名称并检查曲目是否有明确的键。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Major Version</key><integer>1</integer>
    <key>Minor Version</key><integer>1</integer>
    <key>Date</key><date>2014-08-24T05:21:40Z</date>
    <key>Application Version</key><string>11.3.1</string>
    <key>Features</key><integer>5</integer>
    <key>Show Content Ratings</key><true/>
    <key>Music Folder</key><string>file://localhost/C:/Users/Mon%20Tolentino/Music/iTunes/iTunes%20Media/</string>
    <key>Library Persistent ID</key><string>15CDC06EC711077D</string>
    <key>Tracks</key>
    <dict>
        <key>766</key>
        <dict>
            <key>Track ID</key><integer>766</integer>
            <key>Name</key><string>Say Something</string>
            <key>Artist</key><string>A Great Big World</string>
            <key>Album Artist</key><string>A Great Big World</string>
            <key>Composer</key><string>Ian Axel, Chad Vaccarino, Mike Campbell</string>
            <key>Album</key><string>Is There Anybody Out There?</string>
            <key>Grouping</key><string>Indie</string>
            <key>Genre</key><string>Pop</string>
            <key>Kind</key><string>AAC audio file</string>
            <key>Size</key><integer>8639959</integer>
            <key>Total Time</key><integer>233289</integer>
            <key>Disc Number</key><integer>1</integer>
            <key>Disc Count</key><integer>1</integer>
            <key>Track Number</key><integer>5</integer>
            <key>Track Count</key><integer>13</integer>
            <key>Year</key><integer>2013</integer>
            <key>BPM</key><integer>94</integer>
            <key>Date Modified</key><date>2014-05-25T15:58:35Z</date>
            <key>Date Added</key><date>2014-05-18T10:09:13Z</date>
            <key>Bit Rate</key><integer>256</integer>
            <key>Sample Rate</key><integer>44100</integer>
            <key>Play Count</key><integer>33</integer>
            <key>Play Date</key><integer>3491589574</integer>
            <key>Play Date UTC</key><date>2014-08-22T13:59:34Z</date>
            <key>Skip Count</key><integer>7</integer>
            <key>Skip Date</key><date>2014-08-15T15:15:43Z</date>
            <key>Release Date</key><date>2013-11-04T12:00:00Z</date>
            <key>Rating</key><integer>60</integer>
            <key>Album Rating</key><integer>60</integer>
            <key>Album Rating Computed</key><true/>
            <key>Artwork Count</key><integer>1</integer>
            <key>Sort Album Artist</key><string>A Great Big World</string>
            <key>Sort Artist</key><string>A Great Big World</string>
            <key>Persistent ID</key><string>50A143EFFA8BEA97</string>
            <key>Track Type</key><string>File</string>
            <key>Location</key><string>file://localhost/C:/Users/Mon%20Tolentino/Music/iTunes/iTunes%20Media/Music/A%20Great%20Big%20World/Is%20There%20Anybody%20Out%20There_/05%20Say%20Something.m4a</string>
            <key>File Folder Count</key><integer>5</integer>
            <key>Library Folder Count</key><integer>1</integer>
        </dict>

我在网上发现了这个:

    Dim itunesLib As XElement = XElement.Load("xmllocation")

    Dim itunesPlaylists = From key In itunesLib...<key> Where key.Value = "Name"
                          Select key.ElementsAfterSelf("string").Value

    List1.ItemsSource = itunesPlaylists

但它只列出了列表框中的所有曲目,任何人都可以帮助我。

3 个答案:

答案 0 :(得分:1)

哇,这是我见过的最糟糕的XML之一。我不得不忍受这一点表示哀悼。

我很想开始将它们解析为(可能是延期的)具体类的集合,然后.Where那些找到你正在寻找的那个。

我在C#中编写了所有这些代码,原因是我实际上并不真正了解VB,然后使用在线工具进行转换,所以请告诉我这是否有问题,或者是否有任何问题不是最好的实践。但它应该传达工作流程的要点,这才是真正的重点。

那么,我开始写一堂课:

Public Class Track
    Public Property Name() As String
        Get
            Return m_Name
        End Get
        Set
            m_Name = Value
        End Set
    End Property
    Private m_Name As String
    Public Property Explicit() As Boolean
        Get
            Return m_Explicit
        End Get
        Set
            m_Explicit = Value
        End Set
    End Property
    Private m_Explicit As Boolean
End Class

然后我写了一个方法来获取<dict>元素中任意键的值

Private Function GetValue(Of T)(dict As XElement, key As String) As T
    Dim element = dict.Elements("key").FirstOrDefault(Function(c) String.Equals(DirectCast(c, String), key))

    If element Is Nothing OrElse element.NextNode Is Nothing Then
        Return Nothing
    End If

    element = element.NextNode

    If T = GetType(Boolean) Then
        Return element.Name = "true"
    Else
        Return DirectCast(element, T)
    End If
End Function

然后将XML解析为该类:

Dim root = XElement.Load(path)

root = root.Element("dict")

Dim tracks = root.Elements("key").First(Function(c) DirectCast(c, String) = "Tracks").NextNode.Elements("dict")

Dim parsedTracks As IEnumerable(Of Track) = tracks.[Select](Function(c) New Track() With { _
    Key .Name = GetValue(Of String)(c, "Name"), _
    Key .Explicit = GetValue(Of Boolean)(c, "Explicit") _
})

然后您可以轻松地查询:

Return parsedTracks.First(Function(c) c.Name = desiredTrackName).Explicit

我想要添加大量的错误处理,我确定,但这应该传达一个好方法的要点。您可能想要也可能不想在那里进行.ToArray()通话。这完全取决于你如何使用它。这样,每次通话只会循环一次(因此&#34;延迟&#34;),如果您不经常进行搜索,那就太棒了。但是你可能想要.ToArray()它,以便它全部加载到内存中并且如果你正在进行更多的调用已经解析过。

答案 1 :(得分:0)

有几种方法可以在.net中查询XML文档 你可以使用直接DOM查询

例如:

XmlDOcument doc=new XmlDOcument();
doc.LoadXml("your raw xml");

var plist=doc.DOcumentElement.Children[0]; //my plist
var rootDict=plist.Children[0]; //my root dict
//..
//and so on 

在这里阅读.NET XML DOM API

http://msdn.microsoft.com/en-us/magazine/cc302158.aspx

您还可以使用Xml Query languege:Xpath

http://www.codeproject.com/Articles/9494/Manipulate-XML-data-with-XPath-and-XmlDocument-C

答案 2 :(得分:0)

  

&#34;我想要做的是搜索特定的曲目名称,并检查曲目是否有明确的密钥。&#34;

您可以使用LINQ to XML表达式来检查特定轨道是否显式,例如:

Dim xml As XElement = XElement.Load("xmllocation")
Dim trackName = "Say Something"
Dim query = From d In xml...<dict>
            Where d.Elements("key").Any(Function(name) name.Value = "Name" _
                                            AndAlso (CType(name.NextNode, XElement).Value = trackName)) _
                  And d.Elements("key").Any(Function(exp) exp.Value = "Explicit" _
                                             AndAlso (CType(exp.NextNode, XElement).Name = "true"))
Dim isExplicit As Boolean = query.Any()

或者使用等同于上述LINQ的XPath表达式:

Dim xpath As String = String.Format("//dict[key[.='Name' and following-sibling::string='{0}'] and key[.='Explicit' and following-sibling::true]]", trackName)
Dim isExplicit As Boolean = xml.XPathSelectElements(xpath).Any()

更新:

如果您需要检查曲目旁边的艺术家姓名,您可以在WHERE子句中添加另一个过滤器,如下所示:

Where ....
      And d.Elements("key").Any(Function(artist) artist.Value = "Artist" _
                                 AndAlso (CType(exp.NextNode, XElement).Value = "artist name"))
      And ...