Created
September 28, 2018 06:38
-
-
Save JohnLBevan/cfd5309c07a63bb499cc8ee3fbb4dfc7 to your computer and use it in GitHub Desktop.
This is a quick & dirty script for finding missing labels in DFO365 by comparing those in en-GB with those in es. A lot could be done to make this more re-usable (e.g. currently very focussed on the 2 stated languages / could easily be adapted to run for all languages / with optional filters to restrict the languages reported on); but for now it…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function Convert-XmlToHash { | |
| [CmdletBinding(DefaultParameterSetName = 'XmlDocument')] | |
| Param ( | |
| [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'XmlDocument')] | |
| [System.Xml.XmlDocument]$XmlDocument | |
| , | |
| [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'XmlElement')] | |
| [System.Xml.XmlElement]$InputObject | |
| , | |
| [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'XmlText')] | |
| [System.Xml.XmlText]$XmlText | |
| , | |
| [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'XmlAttribute')] | |
| [System.Xml.XmlAttribute]$XmlAttribute | |
| ) | |
| Process { | |
| switch ($PSCmdlet.ParameterSetName) { | |
| 'XmlDocument' { | |
| $XmlDocument.DocumentElement | Convert-XmlToHash | |
| } | |
| 'XmlElement' { | |
| [System.Xml.XmlNode[]]$children = ([System.Xml.XmlNode[]]$InputObject.Attributes) + ([System.Xml.XmlNode[]]$InputObject.ChildNodes) | |
| [hashtable]@{ | |
| "$($InputObject.LocalName)" = $children | Convert-XmlToHash | |
| } | |
| } | |
| 'XmlText' { | |
| $XmlText.Value | |
| } | |
| 'XmlAttribute' { | |
| [hashtable]@{ | |
| "@$($XmlAttribute.LocalName)" = $XmlAttribute.Value | |
| } | |
| } | |
| } | |
| } | |
| } | |
| function Get-Dfo365LabelFileInfo { | |
| [CmdletBinding()] | |
| Param ( | |
| [Parameter(Mandatory = $true, HelpMessage = 'The path of the MetaData directory. e.g. K:\AosService\PackagesLocalDirectory\')] | |
| [ValidateScript({ | |
| if(-Not ($_ | Test-Path) ){ | |
| throw "$_ is not a valid path" | |
| } | |
| if(-Not ($_ | Join-Path -ChildPath 'ApplicationSuite' | Test-Path) ){ | |
| throw "$_ is not a valid metadata path (i.e. does not contain a definition for the ApplicationSuite model)" | |
| } | |
| return $true | |
| })] | |
| [System.IO.DirectoryInfo]$Path | |
| ) | |
| Process { | |
| $Path | | |
| Get-ChildItem -Recurse -Directory | | |
| Where-Object { $_.PSIsContainer -and $_.Name.Equals('AxLabelFile')} | | |
| Get-ChildItem -Filter '*.xml' | | |
| ForEach-Object { | |
| $currentFilename = $_.FullName | |
| try { | |
| [xml](Get-Content -Path $currentFilename -Raw) | | |
| Where-Object {$_.SelectSingleNode('/AxLabelFile')} | #only return valid label definitions | |
| Convert-XmlToHash | ForEach-Object{[PSCustomObject]$_} | #convert from xml to ps object | |
| Add-Member -MemberType NoteProperty -Name 'ThisFilePath' -Value $currentFilename -PassThru | | |
| Add-Member -MemberType NoteProperty -Name 'RootPath' -Value $Path -PassThru | | |
| Add-Member -MemberType ScriptProperty -Name 'LabelFilePath' -Value {(Join-Path -Path $this.RootPath -ChildPath $this.AxLabelFile.RelativeUriInModelStore)} -PassThru | |
| } catch [System.Management.Automation.PSInvalidCastException] { | |
| if ($_.Exception.InnerException -as [System.Xml.XmlException]) { | |
| #if there's files containing XML that can't be parsed spit out an error, but don't break the flow | |
| Write-Error "'$currentFilename' is not a valid XML file" | |
| } else { | |
| #other types of exception, push up the stack to handle (output the filename in a warning though to help investigate) | |
| Write-Warning "Issue occurred processing '$currentFilename'" | |
| throw | |
| } | |
| } | |
| } | |
| } | |
| } | |
| function Import-Dfo365LabelFile { | |
| [CmdletBinding()] | |
| Param ( | |
| [Parameter(Mandatory = $true, ValueFromPipeline = $true)] | |
| [string]$LabelFilePath | |
| ) | |
| Process { | |
| $result = [System.Collections.Generic.Dictionary[string,string]]::new() | |
| Get-Content -Path $LabelFilePath | | |
| Where-Object {$_ -notlike ';*'} | | |
| ForEach-Object {if($_ -match '^(?<Key>[^=]*)=(?<Value>.*)$'){$result.Add($Matches['Key'], $Matches['Value'])}} | |
| $result | |
| } | |
| } | |
| Clear-Host | |
| #expand the output width so stuff doesn't get truncated | |
| $host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size(800,20000) | |
| [PSObject[]]$labelFiles = Get-Dfo365LabelFileInfo -Path 'K:\AosService\PackagesLocalDirectory' | |
| [PSObject[]]$en = $labelFiles | Where-Object {$_.AxLabelFile.Language -eq 'en-GB'} | |
| [PSObject[]]$es = $labelFiles | Where-Object {$_.AxLabelFile.Language -eq 'es'} | |
| $labelFiles = $null | |
| Write-Host 'Files in common' -ForegroundColor Green | |
| $labelFileIds = $en.AxLabelFile.LabelFileId | Where-Object {$_ -in @($es.AxLabelFile.LabelFileId)} | Sort-Object -Unique | |
| $labelFileIds | |
| Write-Host 'Files we have for EN-GB but not ES' -ForegroundColor Green | |
| $en.AxLabelFile.LabelFileId | Where-Object{-not ($_ -in @($labelFileIds))} | |
| Write-Host 'Files we have for ES but not EN-GB' -ForegroundColor Green | |
| $es.AxLabelFile.LabelFileId | Where-Object{-not ($_ -in @($labelFileIds))} | |
| #reduce our data to the intersects, so we can compare at label file level | |
| $en = $en | Where-Object{$_.AxLabelFile.LabelFileId -in @($labelFileIds)} | |
| $es = $es | Where-Object{$_.AxLabelFile.LabelFileId -in @($labelFileIds)} | |
| Write-Host 'Missing Labels' -ForegroundColor Green | |
| $enDict = [System.Collections.Generic.Dictionary[string,[System.Collections.Generic.Dictionary[string,string]]]]::new() | |
| $esDict = [System.Collections.Generic.Dictionary[string,[System.Collections.Generic.Dictionary[string,string]]]]::new() | |
| $en | ForEach-Object { $enDict.Add($_.AxLabelFile.LabelFileId, ($_.LabelFilePath | Import-Dfo365LabelFile))} | |
| $es | ForEach-Object { $esDict.Add($_.AxLabelFile.LabelFileId, ($_.LabelFilePath | Import-Dfo365LabelFile))} | |
| $en = $null | |
| $es = $null | |
| $labelFileIds | ForEach-Object { | |
| [string]$labelFileId = $_ | |
| [string[]]$labelIds = @($enDict[$labelFileId].Keys) + @($esDict[$labelFileId].Keys) | Sort-Object -Unique | |
| $labelIds | ForEach-Object { | |
| $labelId = $_ | |
| [pscustomobject]@{ | |
| LabelFileId = $labelFileId | |
| LabelId = $labelId | |
| en = if ($enDict.ContainsKey($labelFileId) -and $enDict[$labelFileId].ContainsKey($labelId)) {$enDict[$labelFileId][$labelId]} else {$null} #$enDict[$labelFileId][$labelId] | |
| es = if ($esDict.ContainsKey($labelFileId) -and $esDict[$labelFileId].ContainsKey($labelId)) {$esDict[$labelFileId][$labelId]} else {$null} #$esDict[$labelFileId][$labelId] | |
| } | |
| } | |
| } | Where-Object {[String]::IsNullOrWhiteSpace( $_.en ) -or [String]::IsNullOrWhiteSpace( $_.es )} | #Where-Object {$_.en -ne $_.es} | #use this latter where for differing labels | |
| Format-Table -Property LabelFileId, LabelId ,en, es -AutoSize | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment