2011-11-17 114 views
18

我想读取XML文件并修改一个元素,然后将其保存回文件。在保留格式并保持匹配行结束符(CRLF与LF)的同时,做到这一点的最佳方法是什么?PowerShell保存XML并保留格式

这里是我有什么,但它没有做到这一点:

$xml = [xml]([System.IO.File]::ReadAllText($fileName)) 
$xml.PreserveWhitespace = $true 
# Change some element 
$xml.Save($fileName) 

的问题是,额外新行(在XML又名空行)被删除,我有混合LF和CRLF之后。为帮助了一个PowerShell新手:)

+1

“保存格式”是什么意思? – manojlds

+1

它可能不会有所作为,但是您是否尝试过使用'$ xml = [xml](Get-Content $ filename)'而不是?否则,您可能必须使用本机.NET XmlDocument类和方法来加载,编辑和保存文件。 – Ryan

+2

@manojids我想保存空白,换行符,标签等。 –

回答

32

您可以使用PowerShell的[XML]对象,并设置$xml.PreserveWhitespace = $true,或利用.NET XmlDocument的做同样的事情

感谢:

$f = '.\xml_test.xml' 

# Using .NET XmlDocument 
$xml = New-Object System.Xml.XmlDocument 
$xml.PreserveWhitespace = $true 

# Or using PS [xml] (older PowerShell versions may need to use psbase) 
$xml = New-Object xml 
#$xml.psbase.PreserveWhitespace = $true # Older PS versions 
$xml.PreserveWhitespace = $true 

# Load with preserve setting 
$xml.Load($f) 
$n = $xml.SelectSingleNode('//file') 
$n.InnerText = 'b' 
$xml.Save($f) 

只要确保在调用XmlDocument.Load或XmlDocument.LoadXml之前设置PreserveWhitespace

注意:这不保留XML属性之间的空白!空白in XML属性似乎被保留,但不是,在之间。该文件谈到保留“空白节点”(node.NodeType = System.Xml.XmlNodeType.Whitespace)而不是属性

+3

什么是本地PowerShell类型?一切都是.NET :) – manojlds

+1

使用.NET对象修复它。 –

+2

@manojlds你是对的,虽然PS在本例中封装了一些.NET类型(psbase),所以即使它仍然是.NET,它“感觉”有点不同。 :) – Ryan

1

如果使用XmlWriter保存,默认选项是用两个空格缩进并用CR/LF替换行结尾。您可以在创建编写器之后配置这些选项,或者使用配置了您需要的XmlSettings对象创建编写器。

$fileXML = New-Object System.Xml.XmlDocument 

    # Try and read the file as XML. Let the errors go if it's not. 
    [void]$fileXML.Load($file) 

    $writerXML = [System.Xml.XmlWriter]::Create($file) 
    $fileXML.Save($writerXML) 
+0

尽管您可以提供更多详细信息,但请投票表决。当需要xml输出而没有*美化*间距时,这是特别有用的。 – TNT

0

如果你想纠正了被转换为LF文本节点调用的XmlDocument的Save方法可以使用XmlWriterSettings实例后的CRLF。 使用与MilesDavies192s answer相同的XmlWriter,但也会将编码更改为utf-8并保留缩进。

$xml = [xml]([System.IO.File]::ReadAllText($fileName)) 
$xml.PreserveWhitespace = $true 

# Change some element 

#Settings object will instruct how the xml elements are written to the file 
$settings = New-Object System.Xml.XmlWriterSettings 
$settings.Indent = $true 
#NewLineChars will affect all newlines 
$settings.NewLineChars ="`r`n" 
#Set an optional encoding, UTF-8 is the most used (without BOM) 
$settings.Encoding = New-Object System.Text.UTF8Encoding($false) 

$w = [System.Xml.XmlWriter]::Create($fileName, $settings) 
try{ 
    $xml.Save($w) 
} finally{ 
    $w.Dispose() 
}