如何将 XmlDocument 保存到 .csproj "formatted like Visual Studio",其中空元素保存在单独的行中?
How to save an XmlDocument to a .csproj "formatted like Visual Studio" where empty elements are saved on separate lines?
目前我已经创建了一个 PowerShell 脚本来处理数百个(是的,数百个)Visual Studio 项目并更新参考以保持一致性,这修复了一些细微的错误。这适用于能够 往返 99% 的 XML,这样 Visual Studio 中的后续编辑项目文件就不会引入其他更改。
但是,对于 XmlDocument.Save()
,EMPTY 元素在同一行上保存为一对..
<StartupObject></StartupObject>
..而不是 Visual Studio 项目编辑器 保存拆分为两行的 EMPTY 元素的方式 ..
<StartupObject>
</StartupObject>
这会导致在初始提交时出现不必要的噪音,随着程序员从 Visual Studio.
中更新项目,这些噪音将被重置
如何使用相同的格式规则 Visual Studio [至少截至 2017 年] 使用 Visual Studio [修改] XmlDocument
保存?
目前保存是使用显式 XmlWriter
和 XmlWriterSettings
使用以下配置完成的:
$writerSettings = New-Object System.Xml.XmlWriterSettings
$writerSettings.Indent = $true
$writerSettings.IndentChars = $indent # value stolen previously
$writer = [System.Xml.XmlWriter]::Create($path, $writerSettings)
$xml.Save($writer)
如果使用XmlDocument.PreserveWhitespace
设置,未修改的节点不受影响。但是,在这种情况下 "improperly formatted" 条目不固定,新节点没有应用正确的 indenting/formatting。
最好可以通过简单修改保存 and/or 设置而不是自定义编写器(因为脚本在 PowerShell 中)或一些 post-保存文本操作(这样感觉有点笨拙)。
虽然一般来说我认为您不应该使用正则表达式篡改 XML,但我也无法在 XmlWriter class 中找到任何会改变写入空元素的样式的设置。
我按照你想要的方式格式化它的唯一方法是让 XmlWriter 写入内存流并在其上使用正则表达式 -replace
:
$writerSettings = New-Object System.Xml.XmlWriterSettings
$writerSettings.Indent = $true
$writerSettings.IndentChars = ' '
$writerSettings.Encoding = New-Object System.Text.UTF8Encoding $false # set to UTF-8 No BOM
# create a stream object to write to
$stream = New-Object System.IO.MemoryStream
$writer = [System.Xml.XmlWriter]::Create($stream, $writerSettings)
$writer.WriteStartDocument()
$writer.WriteStartElement("Root")
$writer.WriteElementString("StartupObject", [string]::Empty)
$writer.WriteElementString("AnotherEmptyElement", [string]::Empty)
$writer.WriteEndElement()
$writer.WriteEndDocument()
$writer.Flush()
$writer.Dispose()
# get whatever is written to the stream in a string variable
$xml = [System.Text.Encoding]::Default.GetString(($stream.ToArray()))
# replace self-closing elements: <StartupObject />
# replace empty elements in one line: <StartupObject></StartupObject>
# to the format where opening and closing tags are on separate lines
$format = '<>{0}</>' -f [Environment]::NewLine
$xml = $xml -replace '(.*?)<(.*?)\s*/>', $format -replace '(.*?)<(.*?)></(.*?)>', $format
# save do disk
$xml | Out-File -FilePath 'D:\test.xml' -Force -Encoding default
结果:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<StartupObject>
</StartupObject>
<AnotherEmptyElement>
</AnotherEmptyElement>
</Root>
目前我已经创建了一个 PowerShell 脚本来处理数百个(是的,数百个)Visual Studio 项目并更新参考以保持一致性,这修复了一些细微的错误。这适用于能够 往返 99% 的 XML,这样 Visual Studio 中的后续编辑项目文件就不会引入其他更改。
但是,对于 XmlDocument.Save()
,EMPTY 元素在同一行上保存为一对..
<StartupObject></StartupObject>
..而不是 Visual Studio 项目编辑器 保存拆分为两行的 EMPTY 元素的方式 ..
<StartupObject>
</StartupObject>
这会导致在初始提交时出现不必要的噪音,随着程序员从 Visual Studio.
中更新项目,这些噪音将被重置如何使用相同的格式规则 Visual Studio [至少截至 2017 年] 使用 Visual Studio [修改] XmlDocument
保存?
目前保存是使用显式 XmlWriter
和 XmlWriterSettings
使用以下配置完成的:
$writerSettings = New-Object System.Xml.XmlWriterSettings
$writerSettings.Indent = $true
$writerSettings.IndentChars = $indent # value stolen previously
$writer = [System.Xml.XmlWriter]::Create($path, $writerSettings)
$xml.Save($writer)
如果使用XmlDocument.PreserveWhitespace
设置,未修改的节点不受影响。但是,在这种情况下 "improperly formatted" 条目不固定,新节点没有应用正确的 indenting/formatting。
最好可以通过简单修改保存 and/or 设置而不是自定义编写器(因为脚本在 PowerShell 中)或一些 post-保存文本操作(这样感觉有点笨拙)。
虽然一般来说我认为您不应该使用正则表达式篡改 XML,但我也无法在 XmlWriter class 中找到任何会改变写入空元素的样式的设置。
我按照你想要的方式格式化它的唯一方法是让 XmlWriter 写入内存流并在其上使用正则表达式 -replace
:
$writerSettings = New-Object System.Xml.XmlWriterSettings
$writerSettings.Indent = $true
$writerSettings.IndentChars = ' '
$writerSettings.Encoding = New-Object System.Text.UTF8Encoding $false # set to UTF-8 No BOM
# create a stream object to write to
$stream = New-Object System.IO.MemoryStream
$writer = [System.Xml.XmlWriter]::Create($stream, $writerSettings)
$writer.WriteStartDocument()
$writer.WriteStartElement("Root")
$writer.WriteElementString("StartupObject", [string]::Empty)
$writer.WriteElementString("AnotherEmptyElement", [string]::Empty)
$writer.WriteEndElement()
$writer.WriteEndDocument()
$writer.Flush()
$writer.Dispose()
# get whatever is written to the stream in a string variable
$xml = [System.Text.Encoding]::Default.GetString(($stream.ToArray()))
# replace self-closing elements: <StartupObject />
# replace empty elements in one line: <StartupObject></StartupObject>
# to the format where opening and closing tags are on separate lines
$format = '<>{0}</>' -f [Environment]::NewLine
$xml = $xml -replace '(.*?)<(.*?)\s*/>', $format -replace '(.*?)<(.*?)></(.*?)>', $format
# save do disk
$xml | Out-File -FilePath 'D:\test.xml' -Force -Encoding default
结果:
<?xml version="1.0" encoding="utf-8"?> <Root> <StartupObject> </StartupObject> <AnotherEmptyElement> </AnotherEmptyElement> </Root>