iTunes xml

This topic contains 1 reply, has 2 voices, and was last updated by Profile photo of Dave Wyatt Dave Wyatt 2 years, 4 months ago.

  • Author
    Posts
  • #17905
    Profile photo of Tony Wainwright
    Tony Wainwright
    Participant

    Hi Guys,

    Has anyone tried comparing 2 iTunes libraries for missing albums. What I've got so far is

    #Get contents of Library.xml
    [xml]$PCDrive = Get-Content "C:\Scripts\OfficePC.xml"
    [xml]$NAS = Get-Content "C:\Scripts\Diskstation.xml"
    
    #Get Albums from Library.xml
    $PCAlbums = $PCDrive..Album
    $NASAlbums = $NASDrive..Album
    
    #Compare Albums (and Output to file)
    Compare-Object -ReferenceObject $PCAlbums -DifferenceObject $NASAlbums

    I've not tried using xml before and have tried looking at the xml but can't work out what I need to put into $PCAlbums and $NASAlbums from the files (Sample Attached)

    Any help would be greatly appreciated – I've over 600 albums and one has not synced so I thought PS would be a good tool

    Thanks
    Tony

  • #17910
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    That is a seriously ugly XML format... way to go, Apple. :\ Instead of using XML elements or attributes to identify things, they seem to be doing everything with a [b]key[/b] element followed by some data type ([b]integer[/b] , [b]string[/b] , [b]dict[/b] , etc). That means the order of the elements in the file is important, and things like XPath (or simple PowerShell code) are just about worthless for navigating its contents.

    Here's an example of what their ridiculous XML file should have looked like (note: All angle brackets have been replaced with square brackets, because the angle brackets screw with our forum software at the moment.)

    [?xml version="1.0" encoding="UTF-8"?]
    [RootNode]
        [MajorVersion]1[/MajorVersion]
        [MinorVersion]1[/MinorVersion]
        [Date]2014-07-30T23:00:36Z[/Date]
        [ApplicationVersion]11.3[/ApplicationVersion]
        [Features]5[/Features]
        [MusicFolder]file://localhost/D:/Users/Public/Public%20Music/iTunes/[/MusicFolder]
        [LibraryPersistentID]BDD9B4CE963E9B3C[/LibraryPersistentID]
    
        [Tracks]
            [Track]
                [TrackID]1263[/TrackID]
                [Album]Bigger, Better, Faster, More![/Album]
            [/Track]
        [/Tracks]
    [/RootNode]
    

    Here's what the code to pull album names out of a file with that sane format would have been:

    $xml = [xml](Get-Content -Path .\test.xml)
    
    $albums = $xml.RootNode.Tracks.Track.Album | Get-Unique
    

    And here's what the code to extract album names from their actual format might look like... 70+ lines to accomplish the work that should have been done with two:

    function Import-AlbumsFromStupidITunesXml
    {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory = $true)]
            [ValidateScript({
                if (Test-Path -LiteralPath $_)
                {
                    return $true
                }
    
                throw "Path '$_' does not exist."
            })]
            [string]
            $Path
        )
    
        $xml = [xml](Get-Content -LiteralPath $Path)
    
        $xml.plist.dict |
        Get-ValueForAppleDictionaryKey -KeyName Tracks -ValueType dict |
        Get-ValueForAppleDictionaryKey -ValueType dict |
        Get-ValueForAppleDictionaryKey -KeyName Album -ValueType string |
        ForEach-Object { $_.InnerText } |
        Get-Unique
    }
    
    function Get-ValueForAppleDictionaryKey
    {
        param (
            [Parameter(ValueFromPipeline = $true)]
            [ValidateScript({
                if ($_.Name -eq 'dict') { return $true }
                throw 'Only  elements may be passed to this command'
            })]
            [System.Xml.XmlElement]
            $Dictionary,
    
            [string]
            $KeyName,
    
            [ValidateSet('integer', 'string', 'dict')]
            [string]
            $ValueType
        )
    
        process
        {
            if ($null -eq $Dictionary)
            {
                return
            }
    
            $childCount = $Dictionary.ChildNodes.Count
    
            for ($i = 0; $i -lt $childCount-1; $i++)
            {
                $node = $Dictionary.ChildNodes[$i]
                $nextNode = $Dictionary.ChildNodes[$i + 1]
    
                if ($node.Name -eq 'key' -and
                    ([string]::IsNullOrEmpty($KeyName) -or $node.InnerText -eq $KeyName) -and
                    ([string]::IsNullOrEmpty($ValueType) -or $nextNode.Name -eq $ValueType))
                {
                    $nextNode
                    $i++
                }
            }
        }
    }
    
    $albums = Import-AlbumsFromStupidITunesXml -Path '.\test.xml'
    $albums
    

You must be logged in to reply to this topic.