Powershell XMLDocument는 BOM없이 UTF-8로 저장

Aug 19 2020

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 파일을 열고이를 BOM없이 UTF-8로 저장하면 다른 스크립트에는 문제가 없습니다. 그래서 BOM없이 스크립트를 저장하라는 요청을 받았습니다.

저장 방법에 대한 MS의 문서 상태 :

인코딩 특성의 값은 XmlDeclaration.Encoding 속성에서 가져옵니다. XmlDocument에 XmlDeclaration이 없거나 XmlDeclaration에 인코딩 특성이없는 경우 저장된 문서에도 인코딩 특성이 없습니다.

XmlDeclaration에 대한 MS 문서 에는 UTF-8, UTF-16 등의 인코딩 속성이 나열되어 있습니다. BOM은 언급하지 않습니다.

XmlDeclaration에 BOM을 제거하는 인코딩 속성이 있습니까?

추신. 이 동작은 Powershell 5 및 Powershell 7에서 동일합니다.

답변

2 mklement0 Aug 19 2020 at 09:39

안타깝게도 encoding="utf-8"XML 문서 선언에 속성 이 명시 적으로 존재 하면 대상 파일 경로가 제공되는 경우 BOM.Save() 이있는 UTF-8 인코딩 파일 문서에 대한 .NET이 발생하여 실제로 문제가 발생할 수 있습니다.

이 변경 요청 은 이전 버전과의 호환성이 깨질 까봐 거부되었습니다. 여기 에 최소한 동작을 문서화 하라는 요청 이 있습니다.

다소 역설적 부재encoding특성 발생 .Save()UTF-8 인코딩 된 파일을 생성 하지 않고 BOM이.

따라서 간단한 해결책은 인코딩 속성 [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을 기본값으로 효과적으로 지정 하기 때문에 안전 합니다.

1 MathiasR.Jessen Aug 19 2020 at 05:20

BACON이 주석에서 설명 했듯이 EncodingXML 선언 의 속성 문자열 값은 문서를 포함하는 파일이 인코딩되는 방식과 관련이 없습니다.

당신이 중 하나 작성하여이를 제어 할 수 있습니다 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 })

두 번째 인수는 [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>