Найдите и выберите атрибут xml между двумя файлами с помощью PowerShell

#xml #powershell

#xml #powershell

Вопрос:

У меня есть два XML-файла.

File1.xml:

 <fileAsset fileAssetGuid="guid1" assetTitle="Title1" />
<fileAsset fileAssetGuid="guid2" assetTitle="Title2" />
<fileAsset fileAssetGuid="guid3" assetTitle="Title3" />
  

File2.xml:

 <file id="guid1" />
<file id="guid2" />
<file id="guid3" />
  

Я знаю значение assetTitle в File1.xml («Title1»). Мне нужно использовать это значение, чтобы получить / выбрать значение fileAssetGuid («guid1») в file1.xml . Затем мне нужно использовать значение («guid1») fileAssetGuid в file1.xml чтобы найти идентификатор («guid1») в file2.xml .

Как мне выполнить это в PowerShell?

Ответ №1:

Следующее должно делать то, что вы хотите (я добавил материал в иллюстративных целях):

 PS D:MiLuDevPowerShell> cat .xmlsel1.xml
<file1>
<fileAsset fileAssetGuid="guid1" assetTitle="Title1" />
<fileAsset fileAssetGuid="guid2" assetTitle="Title2" />
<fileAsset fileAssetGuid="guid3" assetTitle="Title3" />
</file1>
PS D:MiLuDevPowerShell> cat .xmlsel2.xml
<file2>
<file id="guid1" data="one" />
<file id="guid2" data="two" />
<file id="guid3" data="three" />
</file2>
PS D:MiLuDevPowerShell> cat .xmlsel.ps1
$doc1 = [xml](get-content xmlsel1.xml)
$title = "Title2"
$asset = $doc1.file1.fileAsset | where { $_.assetTitle -eq $title }
# echo $asset
# echo $asset.assetTitle
# echo $asset.fileAssetGuid

$doc2 = [xml](get-content xmlsel2.xml)
$file = $doc2.file2.file | where { $_.id -eq $asset.fileAssetGuid }
# echo $file
echo $file.data
PS D:MiLuDevPowerShell> .xmlsel.ps1
two
  

Ответ №2:

Используйте Xpath.

 # Load up the XML 1. I've used here-string, but anything goes.
[xml]$x1 = @'
<root>
<fileAsset fileAssetGuid="guid1" assetTitle="Title1" />
<fileAsset fileAssetGuid="guid2" assetTitle="Title2" />
<fileAsset fileAssetGuid="guid3" assetTitle="Title3" />
</root>
'@

# Ditto for XML 2.
[xml]$x2 = @'
<root>
<file id="guid1" />
<file id="guid2" />
<file id="guid3" />
</root> 
'@

# Look for fileAsset element that has assettitle attribute
# which has value Title1
$n=$x1.SelectSinglenode("/root/fileAsset[@assetTitle='Title1']")

# Look for file node from XML2 that has id attribute
# that has value we got from XML1 with assetTitle 
$x2.SelectSingleNode("/root/file[@id=`"$($n.fileAssetGuid)`"]")

# Remove the node by calling its parent's RemoveChild()
$n2.ParentNode.RemoveChild($n2)

# View final XML on the console
$x2.Save([console]::out)
  

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

1. Рассмотрите возможность использования Select-Xml 🙂

2. Код удаления отлично сработал и в основном соответствует стилю, который я в итоге использовал в своем скрипте. Спасибо!

Ответ №3:

Следуя предложению Стеджея.

 Select-Xml -Path "$pwdfile1.xml" -XPath "/root/fileAsset[@assetTitle]" | 
    ForEach {
        $id = $_.Node.fileAssetGuid
        Select-Xml -Path "$pwdfile2.xml" -XPath "/root/file[@id='$id']" | 
            ForEach { $_.Node }
    }

############
############

foreach( $assetGuideRecord in (Select-Xml -Path "$pwdfile1.xml" -XPath "/root/fileAsset[@assetTitle]") ) {
    $id = $assetGuideRecord.node.fileAssetGuid

    foreach( $record in (Select-Xml -Path "$pwdfile2.xml" -XPath "/root/file[@id='$id']") ) {
        $record.node
    }
}
  

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

1. Спасибо за ответы выше. Я попробовал метод Select-Xml, и у меня это сработало. Теперь, когда я выбрал узел <идентификатор файла =»guid1″ />, мне нужно удалить его из файла. Каков наилучший способ сделать это?

2. Найдите родительский узел для того, который вы хотите удалить, и удалите его дочерний узел. Согласно моему предыдущему ответу, $n2 = $x2.SelectSingleNode("/root/file[@id= «$($n.fileAssetGuid) "]"); $n2.ParentNode.RemoveChild($n2);$x2.Save([console]::out);

3. Смотрите мой обновленный ответ для синтаксиса удаления в более приятной форме.

4. Потрясающе! Заметил ваш обновленный ответ, который отлично сработал для меня. Спасибо!