我有一个Apple Music Library输出文件,看起来像这样:
<key>6871</key>
<dict>
<key>Track ID</key><integer>6871</integer>
<key>Name</key><string>12 Wake Up Call</string>
<key>Artist</key><string>Rebelution</string>
<key>Album Artist</key><string>Rebelution</string>
<key>Grouping</key><string>AllMusic</string>
<key>Kind</key><string>Apple Music AAC audio file</string>
<key>Size</key><integer>6178208</integer>
<key>Total Time</key><integer>257332</integer>
<key>Year</key><integer>2009</integer>
<key>Date Modified</key><date>2011-11-22T23:32:45Z</date>
<key>Date Added</key><date>2011-12-14T23:30:26Z</date>
<key>Bit Rate</key><integer>256</integer>
<key>Sample Rate</key><integer>44100</integer>
<key>Play Count</key><integer>101</integer>
<key>Play Date</key><integer>3717804040</integer>
<key>Play Date UTC</key><date>2021-10-23T07:20:40Z</date>
<key>Skip Count</key><integer>10</integer>
<key>Skip Date</key><date>2020-09-16T14:39:31Z</date>
<key>Rating</key><integer>60</integer>
<key>Album Rating</key><integer>60</integer>
<key>Album Rating Computed</key><true/>
<key>Normalization</key><integer>1699</integer>
<key>Artwork Count</key><integer>1</integer>
<key>Persistent ID</key><string>56B43C03AFF476E5</string>
<key>Track Type</key><string>Remote</string>
<key>Apple Music</key><true/>
</dict>
我正在努力让它更容易存储在数据库中(我不懂SQL,但这是最终目标(。现在我添加并查找";条目";在excel表格中。我可以通过将XML文件粘贴到工作簿中手动操作它,然后我必须使用ablebits和vlookup以及一系列其他耗时的操作,然后将它们粘贴到新的文本文件中。这个问题的最终目标是得到我的";XML";文件看起来像这样:
<key>5056</key>
<dict>
<TrackID>5056</TrackID>
<Name>Heart Like a Lion</Name>
<Artist>Rebelution</Artist>
<AlbumArtist>Rebelution</AlbumArtist>
<Composer>Eric Ariel Rachmany, Marley D. Williams, Rourke Carey & Wesley Dallas Finley</Composer>
<Album>Courage to Grow</Album>
<Grouping>LIBRARY</Grouping>
<Genre>Reggae</Genre>z
<Kind>Apple Music AAC audio file</Kind>
<Size>11679958</Size>
<TotalTime>338413</TotalTime>
<DiscNumber>1</DiscNumber>
<DiscCount>1</DiscCount>
<TrackNumber>2</TrackNumber>
<TrackCount>12</TrackCount>
<Year>2007</Year>
<DateModified>2021-11-10T08:29:23Z</DateModified>
<DateAdded>2021-11-10T08:29:23Z</DateAdded>
<BitRate>256</BitRate>
<SampleRate>44100</SampleRate>
<PlayCount>8</PlayCount>
<PlayDate>3747937611</PlayDate>
<PlayDateUTC>2022-10-07T01:46:51Z</PlayDateUTC>
<ReleaseDate>2007-06-08T12:00:00Z</ReleaseDate>
<Rating>100</Rating>
<AlbumRating>60</AlbumRating>
<AlbumRatingComputed></AlbumRatingComputed>
<ArtworkCount>1</ArtworkCount>
<SortAlbum>Courage to Grow</SortAlbum>
<SortArtist>Rebelution</SortArtist>
<SortName>Heart Like a Lion</SortName>
<PersistentID>AD1A6E4E78F9C79D</PersistentID>
<TrackType>Remote</TrackType>
<AppleMusic></AppleMusic>
</dict>
任何事情都会有所帮助,这变得比我想象的更耗时、更困难。
我也对其他路线持开放态度。。。我只想备份我的元数据,因为我丢失过一次(如上所述手动恢复(,但我也有一些基于元数据值的时间戳制作播放列表的好主意。
哦,旁注。。。如果更容易的话,我也愿意使用另一种语言。我的代码背景很低,一直在自学AppleScript,因为我的涂鸦主要是与苹果的东西交互。
谢谢!
AppleScriptObjC可用于访问各种Cocoa框架,例如将plist/xml文件读取到NSDictionary(类似于记录(中,在该字典中,可以通过编程方式访问各种键,并用于日期格式化、列表排序等实用程序。
有一个NSXMLNode类可以用来创建元素,但在这种情况下,手动转换字典键并没有那么麻烦。
以下脚本从Apple Music Library导出创建一个纯XML文件。它将指定的关键项目提取到轨道元素中,并使用轨道ID作为元素属性:
use framework "Foundation" -- for the AppleScriptObjC bits
use scripting additions
# the dictionary keys to extract (use an empty list {} for everything):
property keyNames : {"Name", "Kind", "Size", "Total Time", "Date Added", "Track Type", "Location"}
property keepSet : missing value -- this will be an NSSet of the keys
property indent : " " -- formatting
on run -- create an XML file for track data from an exported Music Library plist/XML file
if keyNames is not in {"", {}, missing value} then set keepSet to current application's NSMutableSet's setWithArray:(keyNames as list)
set fileURL to current application's NSURL's fileURLWithPath:(POSIX path of (choose file of type {"com.apple.property-list", "public.xml"} with prompt "Choose the Music Library export file to process:"))
set fileData to current application's NSData's dataWithContentsOfURL:fileURL
try -- read file data (source XML file needs to be in Apple's property list format)
set plist to (current application's NSPropertyListSerialization's propertyListWithData:fileData options:(current application's NSPropertyListMutableContainersAndLeaves) format:(missing value) |error|:(missing value))
if plist is missing value then error "The chosen file is not an Apple plist/XML file."
set trackDict to (plist's valueForKey:"Tracks") -- dictionary of tracks
if trackDict is missing value then error "The chosen file does not have a 'Tracks' key in the root directory."
on error errmess
display alert "Script Error" message errmess
error number -128 -- cancel
end try
set theResult to ""
repeat with trackItem in trackDict's allKeys()
set trackKeyPath to "Tracks." & (trackItem as text) -- dictionary for individual track key
set theResult to theResult & addWrapper(trackItem as text, (XMLtext from (plist's valueForKeyPath:trackKeyPath)))
end repeat
writeToFile((choose file name default name "Converted Library.xml"), addWrapper(missing value, theResult))
end run
# return XML text from simple key/value pairs of a dictionary
on XMLtext from dictionary
set XMLElements to {}
set candidate to current application's NSMutableSet's setWithArray:(dictionary's allKeys())
if keepSet is not missing value then candidate's intersectSet:keepSet -- remove other keys
repeat with keyItem in candidate's allObjects()
try
set theItem to (dictionary's valueForKey:keyItem)
set theValue to theItem as text -- test
on error errmess -- can't coerce object to text
set theClass to current application's NSStringFromClass(theItem's class) as text
if theClass contains "Date" then -- format NSDate
set theValue to (current application's NSISO8601DateFormatter's alloc's init()'s stringFromDate:theItem) as text
else -- something needing additional formatting or processing such as a collection, etc
log theClass & ": " & errmess
set theValue to "*ERROR*" -- or add formatting for the object
end if
end try
set keyName to (keyItem's lowercaseString's stringByReplacingOccurrencesOfString:" " withString:"_") -- no spaces in key names
set end of XMLElements to indent & indent & "<" & keyName & ">" & theValue & "</" & keyName & ">" & linefeed -- can also use NSXMLNode
end repeat
set elementArray to current application's NSArray's arrayWithArray:XMLElements
return (elementArray's sortedArrayUsingSelector:"compare:") as list as text -- sort
end XMLtext
# add wrappers for individual track entries or the document
to addWrapper(theKey, theText)
if theKey is not missing value then -- wrap individual track elements - the key is used as an attribute
return linefeed & indent & "<track id="" & theKey & "">" & linefeed & theText & indent & "</track>" & linefeed
else -- wrapper and root element for a standard XML document
return "<?xml version="1.0" encoding="UTF-8"?>
<!-- track data extracted " & ((current date) as «class isot» as string) & " from exported Apple Music Library -->
<music_tracks>" & theText & "</music_tracks>" & linefeed
end if
end addWrapper
on writeToFile(filePath, whatever)
try
set fileRef to (open for access filePath with write permission)
set eof of fileRef to 0 -- overwrite existing
write whatever to fileRef starting at eof
close access fileRef
on error
try
close access fileRef
end try
end try
end writeToFile