xml - 使用 PowerShell 读取、更新和写入 XML 文档
问题描述
我想读取、更新然后将 Web.config 文件写回磁盘,该文件是一个 XML。我现在的做法是:
[xml]$config = Get-Content -Path $ConfigPath
# Update...
$config.Save($ConfigPath)
问题是它稍微弄乱了初始配置格式。我有一些节点,例如:
<add key="DEBUG_API_ABC" value='
{
"A": {
"B": "asd",
"C": "qwe"
}
}
'/>
它使它像:
<add key="DEBUG_API_ABC" value=" { "..."/>
我想完全按原样保存它,保持格式、文本间距,只在更新时注入一些值。可能吗?
解决方案
加载 XML 文档的正确方法(不仅在 PowerShell 中)是使用 XML 解析器来加载它并避免Get-Content
,因为Get-Content
如果有机会,它会很高兴地破坏文件编码。
您似乎有一个属性中包含 JSON 数据的 XML 文件,这很奇怪,但让我们使用您所拥有的:
$config = New-Object xml
$config.Load $ConfigPath
$debugApi = $config.selectSingleNode("//add[@key='DEBUG_API_ABC']")
$configData = $debugApi.getAttribute("value") | ConvertFrom-JSON
$configData.A.B = "new value"
$configJson = $configData | ConvertTo-JSON
$debugApi.setAttribute("value", $configJson)
$config.Save($ConfigPath)
ConvertTo-JSON
默认情况下将漂亮地打印其输出,因此虽然它可能不会在 JSON 中保持“原始”空白布局,但仍会在 XML 中产生可识别的结构。
关于问题“我可以在属性值中保留"
而不是吗?”"
不,你不能。原因如下:
当涉及序列化“特殊”字符(其中 XML 没有很多,但"
有'
两个)时,XML DOM API 是固执己见的。例如,value='something " something'
是有效的 XML,会导致@value
该节点的属性something " something
解析后获取 RAM 中的字符串值。
然而,当该字符串再次被序列化时,value="something " something"
100% 完全相同——但为了重现原始布局,解析器需要记住在原始文件中,该特定属性具有单引号分隔符。
这是很多额外的工作,它会减慢解析速度,占用更多内存,并且这样做不会使最终结果更正确。所以解析器通常不会,它们使用同样正确但更容易生成的默认值。
例如,DOM API 对序列化的看法可能是“所有属性都使用双引号作为分隔符,因此属性值中的所有双引号都将被转义”,这完全没问题,因为它将保持数据完整性,这才是最重要的。
它还将所有单引号属性“规范化”为双引号属性,使属性中的 JSON 更难阅读。但问题的一部分是,也许将 JSON 存储在 XML 中并不是最好的选择,至少只要您依赖人工编辑器。
推荐阅读
- azure-devops - 无法使用 odata 在 VSTS 中下载“Scrum 任务”的更改历史记录和讨论详细信息
- react-native - 中间件不是本机反应的功能
- android - 使用手势自动静音应用程序 - 如何?
- angular - 将子对象属性名称转换为字符串数组的智能方法?
- python - 空地问题
- tsql - T-SQL 使用日期格式记帐 sql server 的格式
- c - 如何使用指针为 c 中的结构添加多个值?
- reactjs - React JS 中的 ComponentWillMount 和 ComponentDidMount 有什么区别?
- c++ - C ++运行直到按键
- php - 在 curl 中模拟一个真实的浏览器