Powershell XMLDocument BOM olmadan UTF-8 olarak kaydedin
System.Xml.XmlDocument türünde bir XML nesnesi oluşturdum.
$scheme.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False XmlDocument System.Xml.XmlNode
Dosyayı kaydetmek için save () yöntemini kullanıyorum.
$scheme.save()
Bu, dosyayı BOM ile UTF-8 biçiminde kaydeder. BOM, diğer komut dosyalarıyla ilgili sorunlara neden olur.
XML dosyasını Notepad ++ ile açıp UTF-8 olarak kaydettiğimizde (BOM olmadan), satırın altındaki diğer betiklerin bir problemi olmaz. Bu yüzden BOM olmadan komut dosyasını kaydetmem istendi.
Save yöntem MS belgelerine devletler:
Kodlama özniteliğinin değeri, XmlDeclaration.Encoding özelliğinden alınır. XmlDocument bir XmlDeclaration'a sahip değilse veya XmlDeclaration'ın bir kodlama özniteliği yoksa, kaydedilen belgede bir tane de olmayacaktır.
XmlDeclaration MS belgeleri UTF-8, UTF-16 ve diğer özelliklerini kodlayan listeleri. Bir ürün reçetesinden bahsetmez.
XmlDeclaration, BOM'u dışarıda bırakan bir kodlama özelliğine sahip mi?
PS. Bu davranış Powershell 5 ve Powershell 7'de aynıdır.
Yanıtlar
Ne yazık ki, encoding="utf-8"
bir XML belgesinin bildiriminde bir özniteliğin açık varlığı, .NET'in .Save()
belgeye, bir hedef dosya yolu verilirse BOM ile UTF-8 kodlu bir dosyaya gitmesine neden olur ve bu da gerçekten sorunlara neden olabilir.
Geriye dönük uyumluluğu bozma korkusuyla bunu değiştirme isteği reddedildi; İşte en azından davranışı belgelemek için bir istek .
Biraz ironik bir şekilde, bir özniteliğin olmaması , BOM olmadan UTF-8 kodlu dosyaların oluşturulmasına encoding
neden olur ..Save()
Bu nedenle basit bir çözüm, kodlama özniteliğini [1] kaldırmaktır ; Örneğin:
# Create a sample XML document:
$xmlDoc = [xml] '<?xml version="1.0" encoding="utf-8"?><foo>bar</foo>' # Remove the 'encoding' attribute from the declaration. # Without this, the .Save() method below would create a UTF-8 file *with* BOM. $xmlDoc.ChildNodes[0].Encoding = $null # Now, saving produces a UTf-8 file *without* a BOM. $xmlDoc.Save("$PWD/out.xml")
[1] Bunu yapmak güvenlidir, çünkü XML W3C Önerisi , hem bir ürün reçetesi hem de bir encoding
öznitelik olmadığında varsayılan olarak UTF-8'i etkin bir şekilde zorunlu kılar .
BACON'un yorumlarda açıkladığı gibi Encoding
, XML bildirimindeki özniteliğin dize değerinin , belgeyi içeren dosyanın nasıl kodlandığına dair herhangi bir ilgisi yoktur.
Ya bir oluşturarak bu kontrol edebilir StreamWriter
ya da XmlWriter
olmayan bir BOM ile UTF8Encoding
, daha sonra pas o kadar Save($writer)
:
$filename = Resolve-Path path\to\output.xml
# Create UTF8Encoding instance, sans BOM
$encoding = [System.Text.UTF8Encoding]::new($false)
# Create StreamWriter instance
$writer = [System.IO.StreamWriter]::new($filename, $false, $encoding)
# Save using (either) writer
$scheme.Save($writer)
# Dispose of writer
$writer.Dispose()
Alternatif olarak bir kullanın [XmlWriter]
:
# XmlWriter Example
$writer = [System.Xml.XmlWriter]::Create($filename, @{ Encoding = $encoding })
İkinci argüman, [XmlWriterSettings]kodlamayı açıkça ayarlamanın yanı sıra formatlama seçenekleri üzerinde daha fazla kontrol uygulayabileceğimiz bir nesnedir:
$settings = [System.Xml.XmlWriterSettings]@{ Encoding = $encoding
Indent = $true NewLineOnAttributes = $true
}
$writer = [System.Xml.XmlWriter]::Create($filename, $settings)
# <?xml version="1.0" encoding="utf-8"?>
# <Config>
# <Group
# name="PropertyGroup">
# <Property
# id="1"
# value="Foo" />
# <Property
# id="2"
# value="Bar"
# exclude="false" />
# </Group>
# </Config>