2011-11-17 17 views
18

Tôi muốn đọc trong một tệp XML và sửa đổi một phần tử rồi lưu nó trở lại tệp. Cách tốt nhất để làm điều này trong khi bảo quản định dạng và cũng giữ cho phù hợp với Line terminator (CRLF vs LF) là gì?Powershell lưu XML và định dạng bảo toàn

Dưới đây là những gì tôi có nhưng nó không làm điều đó:

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

Vấn đề là tắm mới Lines (aka dòng trống trong xml) được loại bỏ và sau khi tôi đã trộn LF và CRLF.

Cảm ơn vì đã giúp ra một newbie PowerShell :)

+1

Bạn có ý gì khi 'giữ nguyên định dạng'? – manojlds

+1

Nó có thể sẽ không tạo ra sự khác biệt, nhưng bạn đã thử '$ xml = [xml] (Get-Content $ filename)' thay thế? Nếu không, bạn có thể phải sử dụng lớp .NET XmlDocument gốc và các phương thức để tải, chỉnh sửa và lưu tệp. – Ryan

+2

@manojids Tôi muốn bảo quản khoảng trống, dòng mới, tab, v.v. –

Trả lời

32

Bạn có thể sử dụng PowerShell [xml] đối tượng và thiết lập $xml.PreserveWhitespace = $true, hoặc làm điều tương tự sử dụng .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) 

Chỉ cần chắc chắn để đặt PreserveWhitespace trước khi gọi XmlDocument.Load hoặc XmlDocument.LoadXml.

LƯU Ý: Điều này không giữ khoảng trắng giữa các thuộc tính XML! Khoảng trắng trong Thuộc tính XML dường như được giữ nguyên, nhưng không phải là giữa. Tài liệu thảo luận về việc bảo tồn "khoảng trắng các nút" (node.NodeType = System.Xml.XmlNodeType.Whitespace) và không thuộc tính.

+3

Các loại powerhell bản địa là gì? Mọi thứ đều .NET. – manojlds

+1

Sử dụng các đối tượng .NET đã sửa nó. –

+2

@manojlds bạn là chính xác, mặc dù PS đóng gói một số loại .NET như trong trường hợp này (psbase) vì vậy nó "cảm thấy" một chút khác nhau ngay cả khi nó vẫn còn .NET. :) – Ryan

1

Nếu bạn lưu bằng cách sử dụng XmlWriter, các tùy chọn mặc định là thụt lề với hai khoảng trắng và thay thế dòng kết thúc bằng CR/LF. Bạn có thể cấu hình các tùy chọn này sau khi tạo nhà văn hoặc tạo nhà văn với đối tượng XmlSettings được cấu hình theo nhu cầu của bạn.

$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

Bỏ phiếu này mặc dù bạn có thể đã cung cấp thêm chi tiết. Điều này đặc biệt hữu ích khi người ta cần đầu ra xml mà không có khoảng trắng * đẹp đẽ. – TNT

0

Nếu bạn muốn sửa CRLF đó được chuyển thành TĐT cho các nút văn bản sau khi bạn gọi phương thức Save trên XmlDocument bạn có thể sử dụng một trường hợp XmlWriterSettings. Sử dụng cùng một XmlWriter như MilesDavies192s answer nhưng cũng thay đổi mã hóa thành utf-8 và giữ thụt đầu dòng.

$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() 
} 
Các vấn đề liên quan