如何用PowerShell更新XML中指定Document下的同名RecipientEmail节点?
问题需求
我是PowerShell脚本新手,想要更新XML文件中指定<Document>节点下的两个同名<RecipientEmail>节点的值:将**第一个<Document>**下的两个<RecipientEmail>都改为sit@abc.com,其余<Document>下的保持不变。我写了循环处理文件夹中多个XML文件的代码,但没达到预期效果,相关代码和XML结构如下:
原尝试代码1
Get-ChildItem C:\Users\sneha\Desktop\Test *.xml | % { $xml = [xml](Get-Content $_) $element = $xml.SelectNodes("//Document//Recipient") foreach ($elements in $element) { $elements.RecipientId='SIT12345' $elements.RecipientName='SITXYZ' $elements.RecipientAddress1='SITAddress 1' $elements.RecipientAddress2='SITAddress 2' $elements.RecipientAddress3='SITAddress 3' $elements.RecipientFaxNumber='12345678' $elements.RecipientZipcode='sit' $elements.RecipientEmail='sit@abc.com' } $xml.Save($_) }
实际XML结构
<Document> <Recipient> <RecipientType>RELATED PARTY COPY</RecipientType> <RecipientId>SIT12345</RecipientId> <RecipientName>SITXYZ</RecipientName> <RecipientAddress1>SITAddress 1</RecipientAddress1> <RecipientAddress2>SITAddress 2</RecipientAddress2> <RecipientAddress3>SITAddress 3</RecipientAddress3> <RecipientAddress4> </RecipientAddress4> <RecipientZipcode>sit</RecipientZipcode> <RecipientCountryCode>GBR</RecipientCountryCode> <RecipientCountry>UNITED KINGDOM</RecipientCountry> <RecipientFaxNumber>12345678</RecipientFaxNumber> <RecipientEmail>abc.com</RecipientEmail> <RecipientEmail>xyz@victor-buck.com</RecipientEmail> </Recipient> </Document> <Document> <Recipient> <RecipientType>RELATED PARTY COPY</RecipientType> <RecipientId>SIT12345</RecipientId> <RecipientName>SITXYZ</RecipientName> <RecipientAddress1>SITAddress 1</RecipientAddress1> <RecipientAddress2>SITAddress 2</RecipientAddress2> <RecipientAddress3>SITAddress 3</RecipientAddress3> <RecipientAddress4> </RecipientAddress4> <RecipientZipcode>sit</RecipientZipcode> <RecipientCountryCode>GBR</RecipientCountryCode> <RecipientCountry>UNITED KINGDOM</RecipientCountry> <RecipientFaxNumber>12345678</RecipientFaxNumber> <RecipientEmail>abc.com</RecipientEmail> <RecipientEmail>xyz@victor-buck.com</RecipientEmail> </Recipient> </Document>
预期XML结构
<DocumentDelivery> <Document> <Recipient> <RecipientType>RELATED PARTY COPY</RecipientType> <RecipientId>SIT12345</RecipientId> <RecipientName>SITXYZ</RecipientName> <RecipientAddress1>SITAddress 1</RecipientAddress1> <RecipientAddress2>SITAddress 2</RecipientAddress2> <RecipientAddress3>SITAddress 3</RecipientAddress3> <RecipientAddress4> </RecipientAddress4> <RecipientZipcode>sit</RecipientZipcode> <RecipientCountryCode>GBR</RecipientCountryCode> <RecipientCountry>UNITED KINGDOM</RecipientCountry> <RecipientFaxNumber>12345678</RecipientFaxNumber> <RecipientEmail>sit@abc.com</RecipientEmail> <RecipientEmail>sit@abc.com</RecipientEmail> </Recipient> </Document> <Document> <Recipient> <RecipientType>RELATED PARTY COPY</RecipientType> <RecipientId>SIT12345</RecipientId> <RecipientName>SITXYZ</RecipientName> <RecipientAddress1>SITAddress 1</RecipientAddress1> <RecipientAddress2>SITAddress 2</RecipientAddress2> <RecipientAddress3>SITAddress 3</RecipientAddress3> <RecipientAddress4> </RecipientAddress4> <RecipientZipcode>sit</RecipientZipcode> <RecipientCountryCode>GBR</RecipientCountryCode> <RecipientCountry>UNITED KINGDOM</RecipientCountry> <RecipientFaxNumber>12345678</RecipientFaxNumber> <RecipientEmail>abc.com</RecipientEmail> <RecipientEmail>xyz@victor-buck.com</RecipientEmail> </Recipient> </Document> </DocumentDelivery>
原尝试代码2(仍无效)
Get-ChildItem C:\Users\sneha\Desktop\Test *.xml | % { $xml = [xml](Get-Content $_) $element = $xml.SelectNodes("//Document//Recipient") foreach ($elements in $element) { $elementCount=$elements.RecipientEmail.Count if($elementCount -eq 1) { $elements.RecipientEmail='sittest@abc.com' } elif($elementCount -gt 1) { foreach ($node in $xml.SelectNodes("//Document//Recipient//RecipientEmail")) { $node ='sit@abc.com' } } } $xml.Save($_) }
解决方案
你的代码问题在于:
- 第一个代码会修改所有
<Recipient>下的<RecipientEmail>,没有限定只修改第一个<Document> - 第二个代码里
$node ='sit@abc.com'只是给变量赋值,没有修改XML节点的文本内容
以下是修正后的代码,只处理每个XML文件中的第一个<Document>节点下的所有<RecipientEmail>:
Get-ChildItem C:\Users\sneha\Desktop\Test *.xml | ForEach-Object { $xml = [xml](Get-Content $_) # 定位到第一个Document节点下的所有RecipientEmail节点 $firstDocEmails = $xml.SelectNodes("//Document[1]//RecipientEmail") foreach ($emailNode in $firstDocEmails) { # 修改节点的文本内容 $emailNode.InnerText = 'sit@abc.com' } # 保存修改后的XML $xml.Save($_.FullName) }
如果还需要修改第一个<Document>下的其他Recipient属性(比如你原代码里的RecipientId、Name等),可以使用以下代码:
Get-ChildItem C:\Users\sneha\Desktop\Test *.xml | ForEach-Object { $xml = [xml](Get-Content $_) # 获取第一个Document下的Recipient节点 $firstRecipient = $xml.SelectSingleNode("//Document[1]//Recipient") if ($firstRecipient) { # 修改Recipient下的其他属性 $firstRecipient.RecipientId = 'SIT12345' $firstRecipient.RecipientName = 'SITXYZ' $firstRecipient.RecipientAddress1 = 'SITAddress 1' $firstRecipient.RecipientAddress2 = 'SITAddress 2' $firstRecipient.RecipientAddress3 = 'SITAddress 3' $firstRecipient.RecipientFaxNumber = '12345678' $firstRecipient.RecipientZipcode = 'sit' # 修改该Recipient下的所有RecipientEmail foreach ($emailNode in $firstRecipient.SelectNodes(".//RecipientEmail")) { $emailNode.InnerText = 'sit@abc.com' } } $xml.Save($_.FullName) }
关键说明
- 使用
//Document[1]精准定位到第一个<Document>节点,避免修改其他节点 - 修改XML节点内容时,要设置节点的
InnerText属性,而不是直接给变量赋值 - 用
SelectSingleNode和SelectNodes结合,确保只操作目标范围内的节点
内容的提问来源于stack exchange,提问作者user21418581
相关产品推荐
相关产品推荐

