0

i have a simple Array, created with the following Content (loop not shown)

$tmpArray  += $AlarmgroupIndexString + ";" + $LanguageIDString + ";" + $ID_string  + ";" + $_.Value

Is there a possibility to add the Content to a multidimensional Array?

I'll have to filter the entries later. With this setup, that's not possible. I have made an attempt with the help of

$list = ConvertFrom-Csv $tmpArray -Header "GroupID", "Language", "TextID", "Text" -Delimiter ";"
$list | Sort-Object -Property GroupID, Language, TextID#

Unfortunately the conversion to excel did not result in a column Separation...

Please find my Code here

foreach ($file in $fileNames) {

$Content = [xml](Get-Content -Path $file.FullName)

$ns = New-Object System.Xml.XmlNamespaceManager($Content.NameTable)
$ns=@{DEF="http://br-automation.co.at/AS/VC/Project"}

$AlarmgroupIndex = Select-Xml -Xml $Content -XPath "//DEF:Property[contains(@Name,'Index')]" -namespace $ns | select -ExpandProperty node
$AlarmgroupIndexString = $AlarmgroupIndex.Value
$AlarmgroupLanguageText = Select-Xml -Xml $Content -XPath "//DEF:TextLayer" -namespace $ns | select -ExpandProperty node
$AlarmgroupIndexMap = Select-Xml -Xml $Content -XPath "//DEF:Index" -namespace $ns | select -ExpandProperty node

$LUT =@{}  
$AlarmgroupIndexMap | foreach{
    $LUT.($_.ID) = $_.Value
}

$tmpArray =@() 
$AlarmgroupLanguageText | foreach{ 

   $LanguageIDString = $_.LanguageId
    
        
        $AlarmgroupTextLayer = Select-Xml -Xml $Content -XPath "//DEF:TextLayer[@LanguageId='$LanguageIDString']/DEF:Text" -namespace $ns | select -ExpandProperty node 

        $AlarmgroupTextLayer | foreach{  

            if($LUT.ContainsKey($_.ID))
            {
                $ID_string = $LUT[$_.ID]
            }
            
            $tmpArray  += $AlarmgroupIndexString + ";" + $LanguageIDString + ";" + $ID_string  + ";" + $_.Value 

        }

    $LanguageIDString=""
    
}

$tmpArray | Out-File "$rootPath\test.txt" -Append -Encoding utf8
$list = ConvertFrom-Csv $tmpArray -Header 'GroupID', 'Language', 'TextID', 'Text' -Delimiter ";"
$list | Sort-Object -Property GroupID, Language, TextID

}

TIA

s0Nic
  • 97
  • 6

2 Answers2

3

First of all:

  • $AlarmgroupIndexString + ";" + $LanguageIDString + ";" + $ID_string + ";" + $_.Value is not an array but a string (with sub-strings separated by semicolons)
  • Try to avoid using the increase assignment operator (+=) to create a collection (or a string) as it is exponential expensive (meaning that the cost will increase with each iteration).

It is a pity that you not showing more details about the loop as the result of your question actually depends how you initialize the $tmpArray variable:

  • If you start with a string ($tmpArray = '') or $Null it will continue to append to that string.
  • If you start with a string ($tmpArray = @()) it will continue to append the array (which is probably where you looking for).

If you going to use ConvertFrom-Csv you might also consider to start with a string and separate each row with a newline (e.g. ... + $_.Value + "`r`n")

Anyways, it is also not a good idea to use ConvertFrom-Csv to build a collection of PowerShell objects (for one reason: it will convert all the values to a string), the correct PowerShell way to do this is:

$List = 1..3 | Foreach-Object { # replace 1..3 with your enumerator
    [pscustomobject]@{
        AlarmIndex = $AlarmgroupIndexString
        LanguageIndex = $LanguageIDString
        ID = $ID_string
        Value = $_.Value
    }
}

}


Update based on the added information in the question:
I am not sure what exactly your application is supposed to do, but the loop should be something like:

$list = $AlarmgroupLanguageText | foreach { 

   $LanguageIDString = $_.LanguageId

    $AlarmgroupTextLayer = Select-Xml -Xml $Content -XPath "//DEF:TextLayer[@LanguageId='$LanguageIDString']/DEF:Text" -namespace $ns | select -ExpandProperty node 

    $AlarmgroupTextLayer | foreach{  

        if($LUT.ContainsKey($_.ID))
        {
            $ID_string = $LUT[$_.ID]
        }
        
        [pscustomobject]@{
            GroupID = $AlarmgroupIndexString
            Language = $LanguageIDString
            TextID = $ID_string
            Text = $_.Value
        }
    }
} 

$list | Sort-Object -Property GroupID, Language, TextID
iRon
  • 20,463
  • 10
  • 53
  • 79
  • Thank you for you post. i am working with powershell for the first time and i am still having a hard time. the entry level is very high. could you help me to adapt your code. – s0Nic Aug 24 '20 at 07:54
  • In the first step i want to sort the entrys in a way in need, scnd step would be to create a Output string of each entry line: e.g. Item Name: [Bit no.] [ID] [en]text – s0Nic Aug 24 '20 at 08:30
  • sorting isnt correct: TextID sorting Looks like follwoing: 1,10,11,12 … 2,20,21,22 … 3,30,31. Is there a way to resolve the sort rule more precisely? – s0Nic Aug 24 '20 at 08:36
  • 1
    @s0Nic `Sort-Object` can take a scriptblock as an argument, allowing you arbitrary control over search keying: `$list |Sort-Object {$_.TextID -as [int]}` – Mathias R. Jessen Aug 24 '20 at 08:45
  • "*sorting isnt correct*" , see: [PowerShell sorting problem of decimal numbers](https://stackoverflow.com/a/57992109/1701026). In your case you might also do some think like: `$ID_string = [Int]$LUT[$_.ID]`. If it doesn't answer your comment, please open a new question (check for dupplicates first). – iRon Aug 24 '20 at 08:50
  • "*create a Output string of each entry line: e.g. Item Name: [Bit no.] [ID] [en]text*", did you try: `... |` [`Format-LIst`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/format-list?view=powershell-7). If this doesn't answer this question, please create a new question with explicitly shows the expected output. – iRon Aug 24 '20 at 08:52
  • Thanks to all of you, I will open a new question – s0Nic Aug 24 '20 at 09:31
0

I will suggest you to have a quick look on this article: https://www.andreasbijl.com/powershell-create-collections-of-custom-objects/

You can generate the list you want using the example described in the link above. For your case it should look similar to this:

$list = New-Object System.Collections.ArrayList
your_foreach_loop
{
    $temp = New-Object System.Object
    $temp | Add-Member -MemberType NoteProperty -Name "GroupID" -Value $AlarmgroupIndexString
    $temp | Add-Member -MemberType NoteProperty -Name "Language" -Value $LanguageIDString
    $temp | Add-Member -MemberType NoteProperty -Name "TextID" -Value $ID_string
    $temp | Add-Member -MemberType NoteProperty -Name "Text" -Value $_.Value
    $list.Add($temp)
}
Adrian Ileana
  • 157
  • 1
  • 8