Bag*_*era 4 .net powershell byte-order-mark utf-8
我构建了一个 System.Xml.XmlDocument 类型的 XML 对象。
$scheme.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False XmlDocument System.Xml.XmlNode
Run Code Online (Sandbox Code Playgroud)
我使用 save() 方法将其保存到文件中。
$scheme.save()
Run Code Online (Sandbox Code Playgroud)
这将以带有 BOM 的 UTF-8 格式保存文件。BOM 会导致其他脚本出现问题。
当我们在 Notepad++ 中打开 XML 文件并将其保存为 UTF-8(不含 BOM)时,其他脚本不会出现问题。所以我被要求保存没有 BOM 的脚本。
保存方法的 MS 文档指出:
编码属性的值取自 XmlDeclaration.Encoding 属性。如果 XmlDocument 没有 XmlDeclaration,或者 XmlDeclaration 没有编码属性,则保存的文档也不会具有编码属性。
XmlDeclaration 上的 MS 文档列出了 UTF-8、UTF-16 等的编码属性。它没有提到 BOM。
XmlDeclaration 是否具有省略 BOM 的编码属性?
附言。此行为在 Powershell 5 和 Powershell 7 中是相同的。
正如BACON 在注释中所解释的那样,Encoding包含文档的文件的编码方式没有任何关系。
您可以通过创建 a或带有非 BOM 的StreamWriteran来控制这一点,然后将其传递给:XmlWriterUTF8EncodingSave($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()
Run Code Online (Sandbox Code Playgroud)
或者使用[XmlWriter]:
# XmlWriter Example
$writer = [System.Xml.XmlWriter]::Create($filename, @{ Encoding = $encoding })
Run Code Online (Sandbox Code Playgroud)
第二个参数是一个[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>
Run Code Online (Sandbox Code Playgroud)
不幸的是,在 XML 文档声明中存在显式encoding="utf-8"属性[xml]会导致 .NET 的( System.Xml.XmlDocument).Save()文档类型在给定文件路径时变成带有BOM 的UTF-8 编码文件,这确实会导致问题(即使它不应该[1])。
原则上已批准更改此设置的请求,但从.NET 6.0 起尚未实现(由于有关更改[System.Text.Encoding]::UTF8为不使用 BOM 的大量讨论,在这种情况下.Save()也将自动不再创建 BOM)。
有点讽刺的是,缺少属性会encoding导致.Save()创建没有BOM 的UTF-8 编码文件。
因此,一个简单的解决方案是删除编码属性[2];例如:
# 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")
Run Code Online (Sandbox Code Playgroud)
[1] 根据XML W3C 建议:“以 UTF-8 编码的实体可以以字节顺序标记开头”[BOM]。
[2] 这样做是安全的,因为在没有 BOM 和属性的情况下,XML W3C 建议encoding有效地强制将 UTF-8 作为默认值。
| 归档时间: |
|
| 查看次数: |
5137 次 |
| 最近记录: |