2011-11-17 113 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() 
}