Powershell XMLDocument另存为UTF-8,无需BOM

问题描述

我建立了一个System.Xml.XmlDocument类型的XML对象。

$scheme.gettype()
IsPublic IsSerial Name BaseType                                                         
-------- -------- ---- --------                                                         
True     False    XmlDocument System.Xml.XmlNode 

我使用save()方法将其保存到文件中。

$scheme.save()

这会将文件保存为带有BOM的UTF-8格式。 BOM会导致其他脚本出现问题。

当我们在Notepad ++中打开XML文件并将其另存为UTF-8(不带BOM)时,该行下的其他脚本没有问题。因此,系统要求我保存不含BOM的脚本。

MS documentation for the save method指出:

encoding属性的值来自XmlDeclaration.Encoding属性。如果XmlDocument没有XmlDeclaration,或者XmlDeclaration没有编码属性,则保存的文档也将没有。

MS documentation on XmlDeclaration列出了UTF-8,UTF-16等的编码属性。它没有提到BOM。

XmlDeclaration是否具有可忽略BOM的编码属性?

PS。在Powershell 5和Powershell 7中,此行为相同。

解决方法

不幸的是,在XML文档的声明中明确存在encoding="utf-8"属性会导致.NET将.Save()文档转换为带有BOM的UTF-8编码文件 如果给出了目标文件路径,则确实会导致问题。

A request to change this因担心破坏向后兼容性而被拒绝; here's a request至少可以记录该行为。

具有讽刺意味的是,encoding属性的不存在使.Save()创建了没有 BOM的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]这是安全的,因为在没有BOM和encoding属性的情况下,XML W3C Recommendation有效地将UTF-8强制设置为默认值。

,

BACON explains in the comments一样,XML声明中Encoding属性的字符串值与包含文档的文件的编码方式无关。

您可以通过创建具有非BOM StreamWriter的{​​{1}}或XmlWriter,然后将 that 传递给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]

第二个参数是一个[XmlWriterSettings]对象,除了显式设置的编码外,我们还可以通过它控制格式选项:

# XmlWriter Example
$writer = [System.Xml.XmlWriter]::Create($filename,@{ Encoding = $encoding })

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...