Reputation: 3
I need to add a new element to existing nodes in an XML. The current structure essentially looks like this:
<CommandManagerResults>
<ListReports>
<Row>
<Name>aaa</Name>
</Row>
<Row>
<Name>bbb</Name>
</Row>
</ListReports>
<ListDocuments>
<Row>
<Name>ccc</Name>
</Row>
<Row>
<Name>ddd</Name>
</Row>
</ListDocuments>
</CommandManagerResults>
I need to add an element in all the "Row" nodes. The code I have so far:
$directory = "E:\temp"
cd $directory
[xml]$XmlDocument = Get-Content ".\test.xml"
$ProjectName = $XmlDocument.CreateElement("ProjectName")
$ProjectName.InnerText = "test"
$temp = $XmlDocument.SelectNodes("//Row")
foreach ($row in $temp){
$row.AppendChild($ProjectName)
$XmlDocument.Save($directory + '\test.xml')
}
However, only the very last "Row" node is getting saved with the new "ProjectName" element. I added '$row | FL' inside the foreach loop and it shows each Row as having the ProjectName element as being there through each iteration of the loop, unfortunately no matter if I save inside or after the foreach loop only the last Row node is saving with the ProjectName element. How it's coming out:
<CommandManagerResults>
<ListReports>
<Row>
<Name>aaa</Name>
</Row>
<Row>
<Name>bbb</Name>
</Row>
</ListReports>
<ListDocuments>
<Row>
<Name>ccc</Name>
</Row>
<Row>
<Name>ddd</Name>
<ProjectName>Test</ProjectName>
</Row>
</ListDocuments>
</CommandManagerResults>
What I want the structure to look like in the end:
<CommandManagerResults>
<ListReports>
<Row>
<Name>aaa</Name>
<ProjectName>Test</ProjectName>
</Row>
<Row>
<Name>bbb</Name>
<ProjectName>Test</ProjectName>
</Row>
</ListReports>
<ListDocuments>
<Row>
<Name>ccc</Name>
<ProjectName>Test</ProjectName>
</Row>
<Row>
<Name>ddd</Name>
<ProjectName>Test</ProjectName>
</Row>
</ListDocuments>
</CommandManagerResults>
FYI, very new to Powershell and XMLs so hopefully everything I've said makes sense and I'm at least heading down the right path.
Upvotes: 0
Views: 501
Reputation: 27776
You have to create a new element for each element to be added. Finally, the Save()
call should be only at the end, when you are done with the document.
$temp = $XmlDocument.SelectNodes("//Row")
foreach ($row in $temp){
$ProjectName = $XmlDocument.CreateElement("ProjectName")
$ProjectName.InnerText = "test"
$row.AppendChild($ProjectName)
}
$XmlDocument.Save($directory + '\test.xml')
On a side note [xml]$XmlDocument = Get-Content ".\test.xml"
, while being convenient, is bad practice. It works just by chance, as most XML documents these days are UTF-8 encoded, which happens to be the default encoding used by Get-Content
. But Get-Content
knows nothing about the actual value of the XML "encoding" attribute.
Proper way to load the XML document, while respecting its "encoding" attribute:
$xml = [xml]::new()
$xml.Load((Convert-Path ".\test.xml"))
Upvotes: 1