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: