PowershellXMLDocumentはBOMなしでUTF-8として保存
System.Xml.XmlDocumentタイプのXMLオブジェクトを作成しました。
$scheme.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False XmlDocument System.Xml.XmlNode
save()メソッドを使用してファイルに保存します。
$scheme.save()
これにより、ファイルがBOM付きのUTF-8形式で保存されます。BOMは、他のスクリプトで問題を引き起こします。
XMLファイルをNotepad ++で開き、UTF-8(BOMなし)として保存する場合、他のスクリプトに問題はありません。そのため、BOMなしでスクリプトを保存するように求められました。
saveメソッドのMSドキュメントには、次のように記載されています。
encoding属性の値は、XmlDeclaration.Encodingプロパティから取得されます。XmlDocumentにXmlDeclarationがない場合、またはXmlDeclarationにエンコード属性がない場合、保存されたドキュメントにもエンコード属性はありません。
XMLDECLARATIONオンMSドキュメントUTF-8、UTF-16などの特性をコードリスト。BOMについては触れていません。
XmlDeclarationには、BOMを除外するエンコーディングプロパティがありますか?
PS。この動作は、Powershell5とPowershell7で同じです。
回答
残念ながら、encoding="utf-8"
XMLドキュメントの宣言に属性が明示的に存在すると、ターゲットファイルパスが指定されている場合、.NETから.Save()
ドキュメントへのUTF-8エンコードファイルへのBOMが発生し、実際に問題が発生する可能性があります。
これを変更する要求は、下位互換性を損なうことを恐れて拒否されました。少なくとも動作を文書化するためのリクエストがあります。
皮肉なことに、encoding
属性がないと、BOMなしで.Save()
UTF-8でエンコードされたファイルが作成されます。
したがって、簡単な解決策は、エンコーディング属性を削除することです[1]。例えば:
# 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] XML W3C勧告では、BOMとencoding
属性の両方がない場合、デフォルトとしてUTF-8が効果的に義務付けられているため、これは安全に実行できます。
以下のようBACONはコメントで説明して、文字列値Encoding
XML宣言の属性は、文書を含むファイルのエンコード方法上の任意のベアリングを持っていません。
あなたはどちらか作成することによって、これを制御することができますStreamWriter
またはXmlWriter
非BOMでUTF8Encoding
、その後、渡すことをするには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()
または、[XmlWriter]
:を使用します
# XmlWriter Example
$writer = [System.Xml.XmlWriter]::Create($filename, @{ Encoding = $encoding })
2番目の引数は[XmlWriterSettings]オブジェクトです。これにより、エンコードを明示的に設定するだけでなく、フォーマットオプションをより細かく制御できます。
$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>