简体   繁体   English

如何使用PowerShell编辑和保存XML节点

[英]How to Edit and Save XML nodes with PowerShell

I cannot seem to get this to work. 我似乎无法让这个工作。 I want to use PowerShell to select all nodes of a particular type, edit them, then save back to disk. 我想使用PowerShell选择特定类型的所有节点,编辑它们,然后保存回磁盘。

Here is the starting XML file: 这是起始XML文件:

<Cars>
  <Car>Car1</Car>
  <Car>Car2</Car>
</Cars>

Here is the file after being modified: 这是修改后的文件:

<Cars>
  <Car Text="Car1"></Car>
  <Car Text="Car2"></Car>
</Cars>

Have tried: 试过:

[xml]$xaml = Get-Content -Path "C:\Test\TranslationUtility\cars.xml" |
             Select-Xml -XPath "//Car" |
             Write-Host $_.InnerText;

You need to iterate through the results in the pipeline. 您需要遍历管道中的结果。 You have more than one result from searching for cars. 搜索汽车有多个结果。 At the end, you will want to have % {$_.Node.Text} instead of Write-Host $_.InnerText; 最后,你需要% {$_.Node.Text}而不是Write-Host $_.InnerText; % {$_.Node.Text} Write-Host $_.InnerText;

The % is a shortcut for For-Each Object . %For-Each Object的快捷方式。 So it basically loops through each entry and displays the information you need. 所以它基本上遍历每个条目并显示您需要的信息。

Here is how I'd approach this. 这是我如何处理这个问题。

First, you get the content from the xml file, then you use SelectNodes to find the nodes you want, you iterate them, create the attribute and assign a value. 首先,从xml文件中获取内容,然后使用SelectNodes查找所需的节点,迭代它们,创建属性并分配值。

Once this is done, all that remains is to save the xml back. 完成此操作后,剩下的就是将xml保存回来。

[xml]$MyXML = Get-Content 'C:\__tmp\YourXmlFile.xml'

$Cars  = $MyXML.SelectNodes('//Car')

$Cars | foreach {
$TextAttrib = $_.OwnerDocument.CreateAttribute('text') 
$_.Attributes.Append($TextAttrib) |Out-Null;
$_.SetAttribute('text','My Car text...')
}

$MyXML.Save('C:\__tmp\YourXmlFile.xml')

As you can see, mine only write a static text, My Car text... but you can tailor this to suit your needs. 正如你所看到的,我只会写一个静态文本, 我的汽车文本......但你可以根据自己的需要定制它。

The code you posted should throw a bunch of errors, because Get-Content (without the parameter -Raw ) produces an array of strings, each of which is invalid XML by itself. 您发布的代码应该抛出一堆错误,因为Get-Content (没有参数-Raw )会生成一个字符串数组,每个字符串本身都是无效的XML。 Feeding that into Select-Xml doesn't work. 将其送入Select-Xml不起作用。 Also, your use of the [xml] type accelerator and Write-Host is wrong. 此外,您使用[xml]类型加速器和Write-Host是错误的。

Rule of thumb: 经验法则:

  • If you want to use Select-Xml let it read the file by itself (via its -Path parameter): 如果你想使用Select-Xml让它自己读取文件(通过它的-Path参数):

     $xpath = '//Car' $xmlfile = 'C:\\Test\\TranslationUtility\\cars.xml' Select-Xml -Xpath $xpath -Path $xmlfile 
  • If you want to use Get-Content and the [xml] type accelerator use the SelectNodes() method: 如果要使用Get-Content[xml]类型加速器,请使用SelectNodes()方法:

     $xpath = '//Car' $xmlfile = 'C:\\Test\\TranslationUtility\\cars.xml' [xml]$xml = Get-Content $xmlfile $xml.SelectNodes($xpath) 

However, that alone won't allow you to achieve your desired result, because you want to manipulate XAML files. 但是,仅此一项不允许您实现所需的结果,因为您想要操作XAML文件。 Please don't omit such crucial information from your questions. 请不要忽略您的问题中的重要信息。 I'm only aware because I was just about to respond to your previous question when you deleted it. 我只知道,因为当你删除它时,我正要回复你之前的问题。

XAML files are always using namespaces, so you must use a namespace manager to take care of that, like this: XAML文件始终使用名称空间,因此您必须使用名称空间管理器来处理它,如下所示:

$xpath   = '//ns:Car'
$xmlfile = 'C:\Test\TranslationUtility\cars.xml'
$ns = @{'ns' = 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'}

Select-Xml -Xpath $xpath -Path $xmlfile -Namespace $ns

or like this: 或者像这样:

$xpath   = '//ns:Car'
$xmlfile = 'C:\Test\TranslationUtility\cars.xml'

[xml]$xml = Get-Content $xmlfile

$nsm = New-Object Xml.XmlNamespaceManager($xml.NameTable) $nsm.AddNamespace("ns", $xml.DocumentElement.NamespaceURI)

$xml.SelectNodes($xpath, $nsm)

Since you want to modify the XML data I'd probably go with the latter approach. 既然你想修改XML数据,我可能会采用后一种方法。 That allows you to add an attribute like this: 这允许您添加如下属性:

$i = 1
$xml.SelectNodes($xpath, $nsm) | ForEach-Object {
    [void]$_.SetAttribute('Text', "Car$i")
    $i++
}

Save the modified XML via the Save() method: 通过Save()方法保存修改后的XML:

$xml.Save('C:\path\to\output.xml')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM