Как изменить поведение результатов PowerShell на основе XML и CSV?

#xml #powershell

Вопрос:

Привет, у меня есть сценарий ниже, и когда я запускаю этот сценарий, он генерирует несколько XML-файлов на основе одного основного XML, теперь у этих xml есть информация об имени компьютера, которая должна быть обновлена в xml, как показано ниже-

 <ComputerName>Server1</ComputerName>
 

но показано, как показано ниже, что является неправильным форматом-

 <ComputerName>Server1, server2, server3</ComputerName>
 

PS скрипт как —

 $template = Get-Content -Path 'C:pscriptvjMasterXML.xml' -Raw
$csv= Import-Csv 'C:pscriptvjCH21000546421_ProductID.csv'
Remove-Item 'C:pscriptvjdup.csv'
Remove-Item 'C:pscriptvjuniq.csv'


$csv |
Group-Object -Property ServerName |
Where-Object -FilterScript {
$_.Count -gt 1
} |
Select-Object -ExpandProperty Group| Export-Csv -Path 'C:pscriptvjdup.csv' -NoTypeInformation



Import-Csv -Path 'C:pscriptvjdup.csv' | Group-Object ServerName | ForEach-Object {
# replace the placeholders in the template. Sort the numeric values for neatness as we go.
$template -replace '#Title#', (([int[]]$_.Group.IGPID | Sort-Object) -join ', ') -replace
'#computername#', "<ComputerName>$($_.Name)</ComputerName>" |
Set-Content -Path "C:pscriptvj$($_.Name).xml" -Encoding UTF8
}

$csv |
Group-Object -Property ServerName |
Where-Object -FilterScript {
$_.Count -lt 2
} |
Select-Object -ExpandProperty Group| Export-Csv -Path 'C:pscriptvjuniq.csv' -NoTypeInformation
Import-Csv -Path 'C:pscriptvjuniq.csv' | Group-Object IGPID | ForEach-Object {
# replace the placeholders in the template. Sort the numeric values for neatness as we go.
$template -replace '#computername#',"<ComputerName>$(($_.Group.ServerName) -join ',')</ComputerName>" -replace
'#Title#', ($_.Name) |
Set-Content -Path "C:pscriptvj$($_.Name).xml" -Encoding UTF8

 }
 

Я уверен, что приведенная ниже часть обрабатывает это разделение запятыми, пожалуйста, помогите в том, как его обновить, чтобы он не нарушал или не влиял на код 1 в сценарии.

 $template -replace '#computername#',"<ComputerName>$(($_.Group.ServerName) -join ',')</ComputerName>" -replace
 

Комментарии:

1. Ясно, что код не был написан для этого. Проблема ForEach-Object в том, что as выводит новый файл на каждую запись и не записывается в добавленные строки в один XML-файл.

2. Кроме того, не могли бы вы, пожалуйста, предоставить свои попытки заставить скрипт работать так, как вам нужно? В противном случае это полностью функциональный скрипт.

3. Спасибо Алексу за ваш ответ ! да, скрипт работает нормально, но вывод неверен, или я бы сказал, что это не то, чего я ожидаю. Я ничего не знаю о сценариях, которые уже были в системе, но работали не так, как предполагалось. Я играю с нижеприведенным битом — ‘#имя_компьютера#’,»<имя_компьютера>$(($_.Группа. Имя_сервера) -присоединиться ‘,’)</имя_компьютера>» и это область, в которой я ищу что-то для создания вывода как </имя_компьютера><Имя_компьютера>Server1<имя_компьютера></имя_компьютера> не как </имя_компьютера><имя_компьютера>Server1, server2, server3<имя_компьютера></имя_компьютера>, я попытался изменить join на то, что я хочу, но это не работает.

Ответ №1:

Если я правильно понимаю, вы хотите вывести xml-файл для каждого сервера, найденного в файле «CH21000546421_ProductID.csv», используя шаблон, но у вас возникли проблемы с написанием их для дубликатов имен серверов.

Если ваш шаблон выглядит примерно так:

 <?xml version="1.0" encoding="utf-8"?>
<Servers>
  <Server title="#Title#">#computername#</Server>
</Servers>
 

и ваш входной csv выглядит примерно так:

 "IGPID","ServerName"
123,"Server1"
43,"Server2"
8,"Server3"
11,"Server1"
1,"Server1"
17,"Server3"
 

Тогда приведенный ниже код должен делать то, что вы хотите:

 $template = Get-Content -Path 'C:pscriptvjMasterXML.xml' -Raw
$csv      = Import-Csv -Path 'C:pscriptvjCH21000546421_ProductID.csv' | Group-Object -Property ServerName

# get the duplicate servernames
$dupes = $csv | Where-Object { $_.Count -gt 1 }
# get the unique servernames
$uniq = $csv | Where-Object { $_.Count -lt 2 }
            
# save this as new csv files
$dupes | Select-Object -ExpandProperty Group | Export-Csv -Path 'C:pscriptvjdup.csv' -NoTypeInformation
$uniq  | Select-Object -ExpandProperty Group | Export-Csv -Path 'C:pscriptvjuniq.csv' -NoTypeInformation

# $dupes is already grouped by servername
$dupes | ForEach-Object {
    # remember you're iterating Groups with multiple items here!
    foreach ($item in $_.Group) {
        $template -replace '#Title#', $item.IGPID -replace '#computername#', "<ComputerName>$($item.ServerName)</ComputerName>" |
        # write an xml for each of the duplicates. By appending the IGPID to the name of the file
        Set-Content -Path "C:pscriptvj$($item.ServerName)_$($item.IGPID).xml" -Encoding UTF8
    }
}

# $uniq is already grouped by servername
$uniq | ForEach-Object {
    # or use -replace '#computername#', "<ComputerName>$($_.Group[0].ServerName)</ComputerName>"
    $template -replace '#Title#', $_.Group[0].IGPID -replace '#computername#', "<ComputerName>$($_.Name)</ComputerName>" |
    # write an xml for each of the unique servers.
    Set-Content -Path "C:pscriptvj$($_.Name).xml" -Encoding UTF8
}
 

Теперь у вас есть несколько xml-файлов, по одному для каждого сервера. Все серверы, которые были найдены как дубликаты, имеют имена xml-файлов <servername>_<id>.xml .
На уникальных серверах есть файлы, называемые <servername.xml>

Демонстрационный контент ‘Server1_123.xml’ (один из дубликатов)

 <?xml version="1.0" encoding="utf-8"?>
<Servers>
  <Server title="123"><ComputerName>Server1</ComputerName></Server>
</Servers>
 

Демонстрационный контент единственного уникального сервера во входном файле ‘Server2.xml’:

 <?xml version="1.0" encoding="utf-8"?>
<Servers>
  <Server title="43"><ComputerName>Server2</ComputerName></Server>
</Servers>