Skip to content

Instantly share code, notes, and snippets.

@JohnLBevan
Created September 28, 2018 06:38
Show Gist options
  • Select an option

  • Save JohnLBevan/cfd5309c07a63bb499cc8ee3fbb4dfc7 to your computer and use it in GitHub Desktop.

Select an option

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…
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