I am trying to load song names from an iTunes library export of a plist via Nokigiri:
doc = Nokogiri::XML(open(file.path))
@songs = Array.new
doc.xpath(<XPATH_HERE>).each do |n|
@songs.push(n) #append data to array
end
The beginning of the plist looks like:
<plist version="1.0">
<dict>
<key>Major Version</key><integer>1</integer>
<key>Minor Version</key><integer>1</integer>
<key>Date</key><date>2014-10-15T22:52:19Z</date>
<key>Application Version</key><string>11.4</string>
<key>Features</key><integer>5</integer>
<key>Show Content Ratings</key><true/>
<key>Music Folder</key><string>file://localhost/Users/mike/Music/iTunes/iTunes%20Media/</string>
<key>Library Persistent ID</key><string>280B84572DDCF406</string>
<key>Tracks</key>
<dict>
<key>96</key>
<dict>
<key>Track ID</key><integer>96</integer>
<key>Name</key><string>Get Lucky (Daft Punk cover)</string>
<key>Artist</key><string>Daughter</string>
<key>Kind</key><string>MPEG audio file</string>
<key>Size</key><integer>4716638</integer>
<key>Total Time</key><integer>294112</integer>
<key>Date Modified</key><date>2013-11-12T20:54:14Z</date>
<key>Date Added</key><date>2013-12-18T17:56:09Z</date>
<key>Bit Rate</key><integer>128</integer>
<key>Sample Rate</key><integer>44100</integer>
<key>Persistent ID</key><string>C3B1B6F26134C9C1</string>
<key>Track Type</key><string>File</string>
<key>Location</key><string>file://localhost/Users/mike/Music/iTunes/iTunes%20Media/Music/Daughter/Unknown%20Album/Get%20Lucky%20(Daft%20Punk%20cover).mp3</string>
<key>File Folder Count</key><integer>5</integer>
<key>Library Folder Count</key><integer>1</integer>
</dict>
<key>98</key>
<dict>
<key>Track ID</key><integer>98</integer>
<key>Name</key><string>Swimming in Solace (DJ Fergie Ferg Remash)</string>
<key>Kind</key><string>MPEG audio file</string>
What I am looking to load from each track is the track name string that comes after the name key. The XPath that I thought should work is
/plist/dict[key[. = 'Tracks']/following-sibling::*[1]]/dict[key/following-sibling::*[1]]/dict[key[. = 'Name']/following-sibling::*[1]]/string
That XPath returns:
<string>Get Lucky (Daft Punk cover)</string>
<string>Daughter</string>
<string>MPEG audio file</string>
<string>C3B1B6F26134C9C1</string>
<string>File</string>
<string>file://localhost/Users/mike/Music/iTunes/iTunes%20Media/Music/Daughter/Unknown%20Album/Get%20Lucky%20(Daft%20Punk%20cover).mp3</string>
<string>Swimming in Solace (DJ Fergie Ferg Remash)</string>
<string>MPEG audio file</string>
It seems that, although my XPath is specifying the key for each string, it is in fact taking the 'following-siblings' of all of each dict regardless.
What can I do to make the query more specific so that this portion of the plist would return:
Get Lucky (Daft Punk cover)
and
Swimming in Solace (DJ Fergie Ferg Remash)
The root element <inventory> has three <item> children, and an <other> child. By using an index [N] on a node in an XPath query, we can explicitly select the N-th <item> child element (counting starts at 1, not 0):
To query attributes, you can refer to them as a "child" of the element of which they are an attribute. To distinguish attribute names from element names, they must be prefixed with a @character. An @attribute node may only appear as the very last node in an XPath.
Now in all the forms find the table with id ‘tbl_testdm’. Within the table go to a specific row and column. Within the cell, if there are multiple inputs, then find an input where value = ‘Open RFS’, and this will give us the final XPath of the field. Assume that your intended web element lies in the Panel Table and has some common text.
Copy your XPath. Search it in the Browser (F12 or developer tool window) in the DOM to verify if it is valid or not (See the below image). Pro Tip 1: Make sure it is unique and no other web element appears when you search twice in the DOM.
This is one possible XPath :
/plist/dict[key='Tracks']/dict/dict/key[.='Name']/following-sibling::string[1]
The beginning of the XPath may varies, but I think the most important part is the last 2 path steps (key[.='Name']/following-sibling::string[1]
). It tell to get the closest <string>
element after every <key>Name</key>
element.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With