Найдите / замените XML через Powershell - PullRequest
2 голосов
/ 08 мая 2020

Я ищу способ выполнить поиск в PowerShell по запросу XML do c для поиска определенного c ID, который находится в теге «ID», затем найдите следующий тег и замените его значение на "правда". Идентификаторы будут предоставлены в первом столбце файла csv. Вот пример структуры XML:

<primary>
<main>
<id>47</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>48</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>49</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>50</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>51</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>

Теперь представьте, что файл csv имеет в столбце 1:

47
49

Я бы хотел, чтобы были только эти теги флагов индикатора. обновлено до true.
Любая помощь будет очень признательна !!

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Первое: Не используйте замену регулярного выражения на xml. PowerShell очень способен обрабатывать (действительный) XML.

Как уже отмечалось, XMLyou show недействителен, поскольку в нем отсутствует элемент root.
После исправления XML, охватив все это внутри элемента <root>...</root> вы можете прочитать это так:

[xml]$xml = Get-Content -Path 'D:\Test\input.xml' -Raw

Затем прочтите файл, чтобы обновить идентификаторы. Если этот файл похож на то, что вы нам показываете, текстовый файл, в котором каждый идентификатор находится в отдельной новой строке, используйте это:

$ids = Get-Content -Path 'D:\Test\ids.txt'

Если, однако, этот файл IS файл CSV, что-то вроде

"ID","Something"
"47","Whatever"
"49","Anything"

затем считайте идентификаторы как массив из него, используя:

$ids = (Import-Csv -Path  'D:\Test\ids.csv').ID

Теперь вы можете l oop поверх идентификаторов и изменить значение принадлежности <indicatorflag> тег:

foreach ($id in $ids) {
    ($xml.root.primary.main | Where-Object {$_.id -eq $id}).indicatorflag = 'true'
}

# save the updated XML
$xml.Save('D:\Test\output.xml')
2 голосов
/ 08 мая 2020

Вы можете использовать следующее выражение XPath, чтобы найти узел <indicatorflag>, который является родственником, следующим за узлом <id>49</id>:

//id[. = 49]/following-sibling::indicatorflag

Обобщите и используйте метод Select-Xml или XmlDocument.SelectSingleNode() для получить узлы:

$xml = [xml]@'
<root>
<primary>
<main>
<id>48</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>49</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
</root>
'@

foreach($ID in 48,49){
  $ifNode = $xml.SelectSingleNode("//id[. = $ID]/following-sibling::indicatorflag")
  if($ifNode){
    $ifNode.InnerText = "false"
  }
}

$xml.Save("C:\path\to\output.xml")
...