【问题标题】:Save XML does not format new nodes when formatting preservewhitespace格式化保留空白时,保存 XML 不会格式化新节点
【发布时间】:2017-12-21 08:27:40
【问题描述】:

得到一个包含大量空白格式的大型 XML。我需要向 XML 添加一些节点。我可以用$xml.PreserveWhiteSpace = $true 加载 XML 就好了,然后保存 XML 文件,保留加载的空白。

但是,如果我向加载的 XML 添加一个新节点(使用.AppendChild),则在保存文件时,这个新节点将全部写入 1 行。

如果我在加载源文件时关闭PreserveWhiteSpace,我的新节点会正确保存为空白和缩进。但是,所有原始文件空白都丢失了。

如何使用PreserveWhiteSpace 加载 XML 并且还添加新节点,新节点为每个元素提供适当的新行?

加载代码:

$xmlitems = New-Object Xml
$xmlitems.PreserveWhitespace = $true
$xmlitems.Load($7items_xml)

这里是添加新节点(元素)代码的一部分:

$newrec = $xmlitems.CreateElement("item")
$xmlitems.Items.AppendChild($newrec) | Out-Null
$newrec.SetAttribute("id", $maxid)
$newrec.SetAttribute("name", "plantFibertankTop")

saveXml $xmlitems $7items_xml

保存代码 - $xmlitems$7items_xml(文件名)被传递到这个函数中:

function saveXml([xml]$xml_data,[string]$xml_file){
    Write-Host "Saving $xml_file"
    $enc = New-Object System.Text.UTF8Encoding($false)
    $wrt = New-Object System.XML.XMLTextWriter($xml_file, $enc)
    $wrt.Formatting = 'Indented'
    $wrt.Indentation = 4
    $xml_data.Save($wrt)
    $wrt.Close()
}

注意:此 XML 输入和创建元素都是有效的 XML,并且可以正常工作,但格式除外。

重复和总结:如何在加载的 XML 文件中保留空格,并为我添加的任何新节点/元素获取缩进/格式?我的测试让我相信我只能拥有 1 个,而不是两者。

【问题讨论】:

  • 您的代码中没有 .AppendChild() 调用,因此我们不知道您传递给 saveXml()[xml] ([System.Xml.Document]) 实例是什么。请提供MCVE (Minimal, Complete, and Verifiable Example)
  • 提供相同的样本。很难预测试运行中的结构
  • @Fragtzack:3 年后我面临同样的问题,而世界其他地方似乎都忽略了它。你有没有找到解决这个问题的方法?

标签: xml powershell


【解决方案1】:

到目前为止我最好的方法是格式化 xml 两次,具有格式化 xml 的通用代码:

function script:Write-Xml {
  param(
    [Parameter(Mandatory=$true)][xml]$Xml,
    [Parameter(Mandatory=$false)][Switch]$InternalRepeat
  )

  $private:stringbuilder = New-Object System.Text.StringBuilder
  $private:settings = (New-Object System.Xml.XmlWriterSettings)
  $settings.Indent = $true
  $settings.IndentChars = "  "
  $settings.NewLineChars = "`n"

  $xmlWriter = [System.XML.XmlWriter]::Create($stringbuilder, $settings)
  $Xml.WriteContentTo($xmlWriter)
  $xmlWriter.Flush()
  $xmlWriter.Close()

  if (!$InternalRepeat.IsPresent) {
    return (Write-Xml -Xml $stringbuilder.ToString() -InternalRepeat)
  }
  return $stringbuilder.ToString()
}

像这样使用它,就可以完成这项工作:

Write-Xml -Xml $xmlDoc

我不知道我是如何想到这个想法的,也不知道它为什么会起作用,但至少在 PS 5.1 上,它确实有效;)

【讨论】:

  • 我已经试过了——但这总是给我格式化的 XML。
  • @sommmen:这就是想法:格式化 XML ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多