1) Find the elements you'd like to update by using the SelectNodes function with the appropriate XPath statement.
'//*[(./@tag1=''A'' or ./@tag1=''D'') and ./@tag2 = ''B'']'
The above code says find any element which has an attribute tag1 with values 'A' or 'D' and also has an attribute tag2 with value 'B'.
2) For each element found by that above, assign that element's tag3 attribute with the value of its tag4 attribute.
| %{ #%{ is an alias (i.e. shorthand) for `| foreach-object`
$_.tag3 = $_.tag4
}
Full Solution (with sample data)
$xml = [xml]@"
<xml>
<something tag1="A" tag2="B" tag3="0.00" tag4="2.00" />
<something tag1="C" tag2="B" tag3="0.00" tag4="2.00" />
<something tag1="D" tag2="B" tag3="0.00" tag4="2.00" />
</xml>
"@
$xml.SelectNodes('//*[(./@tag1=''A'' or ./@tag1=''D'') and ./@tag2 = ''B'']') | %{
$_.tag3 = $_.tag4
}
##Demo Output (function from https://blogs.msdn.microsoft.com/powershell/2008/01/18/format-xml/)
function Format-XML ([xml]$xml, $indent=2)
{
$StringWriter = New-Object System.IO.StringWriter
$XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter
$xmlWriter.Formatting = 'indented'
$xmlWriter.Indentation = $Indent
$xml.WriteContentTo($XmlWriter)
$XmlWriter.Flush()
$StringWriter.Flush()
Write-Output $StringWriter.ToString()
}
Format-XML $xml
Update
I also noted that you mentioned reading the XML from file and saving it back to file... whilst in the above I'd just assigned a value to the $xml variable directly, and showed the output on screen.
To read XML from file, use $xml = [raw](get-content 'c:\path\to\file.xml' -raw). More info (in fact, with a slightly different approach) here:
To save XML back to file, just use $xml.Save('c:\path\to\file.xml')
Again, more info and alternate approaches here: