【问题标题】:Save() in powershell is corrupting the xml filepowershell 中的 Save() 正在破坏 xml 文件
【发布时间】:2020-07-12 01:41:54
【问题描述】:

我有一个简单的 xml 文件,其中只使用获取内容并将 xml 文件保存回来。它破坏了 xml 文件并变得无法使用。非常欢迎您的帮助/建议/解决方案。

$xmlfile = 'C:\Test\stack.xml'
[xml]$xmlcontent = (Get-Content $xmlfile)
$xmlcontent.Save($xmlfile)

下面是我的示例 xml 文件,我在这里使用它来运行我上面提到的 powershell 脚本。您可以将以下 xml 保存到文件中以供参考。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fccconfig SYSTEM "fccconfig.dtd">

<fccconfig version="1.2.3">
   <fccdefaults>

      <!-- general -->
      <property name="FCC_CacheLocation" value="C:/Users/Public/sometestCache" overridable="true"/>
      <property name="FCC_LogFile" value="C:/Users/Public/sometestfile.log" overridable="true" />
      <!-- external site access definition -->
      <!-- <site id="013B998A65427E" overridable="true"> -->
         <!-- <parentfsc address="localhost:4567" priority="0"/> -->
         <!-- <parentfsc address="myserverhost:4444" priority="1"/> -->
         <!-- <assignment mode="parentfsc" /> -->
      <!-- </site> -->

      <site id="-987654321" overridable="true">
         <parentfsc address="http://testlink:12345/" priority="0" />
      </site>
      <!--__ANT_MARK__-->

   </fccdefaults>

   <!-- default parentfsc - this is a marker that will be overwritten by the installer -->
   <parentfsc address="address1.com:2020" priority="0" transport="lan"/>
   <parentfsc address="address1.com:2020" priority="1" transport="lan"/>

</fccconfig>

在运行脚本后的第二个 xml 中,添加了未知字符 [] 。而且 xml 文件之间的间距也发生了变化。下面是文件差异的sn-p。

【问题讨论】:

  • 如果您的问题尚未得到完全解答,请考虑 accepting 提供答案或提供反馈。

标签: xml powershell


【解决方案1】:

文字永远比图片好。第 2 行添加的方括号似乎是正常的 xml 东西:How to get rid of square brackets[] after editing and saving an XML file

请注意,文件将使用第 1 行的编码保存。在这种情况下,如果它不存在,则会添加一个 utf8 bom。

可能会阻止重新格式化? Writing in xml does not keep the formatting?

【讨论】:

  • 嗨@js2010 抱歉不明白你想解释什么。我是PowerShell的新手。我也检查了那个链接,我认为这是在 C# 中执行的。我目前正在powershell中执行保存操作。在我的情况下,我想避免xml文件中的[]大括号,如果你检查,缩进也已经完全改变了。我想避免
  • 我认为您无法避免重新缩进。从某种意义上说,保存使它变得“漂亮”。我不知道如何摆脱括号。我觉得把它留在里面就好了。
【解决方案2】:

它损坏了 xml 文件并变得无法使用。

没有没有损坏 - 文件仍然可以被 XML 处理器读取并且具有相同的内容,但由于 System.Xml.XmlDocument 类中内置的(默认)行为(可通过 PowerShell 中的类型加速器 [xml] 访问),其格式已更改

  • (a) 输入 XML 文本中的非重要空白在阅读时被修剪,并且在保存元素时被漂亮地打印(自动分布在多行并带有缩进);结果,文档的视觉结构发生了变化(但不是其内容)。

  • (b) [] 被附加到 document-type declaration (&lt;!DOCTYPE ...[]&gt;) 的末尾以表示一个空的内部子集,显然在文档被添加时总是添加保存到文件 - 同样,从 XML 解析的角度来看,内容没有变化。

  • (c) 保存的文件使用字符编码 UTF-8带有 BOM - 无论输入文件是否有 BOM;原因是 XML 声明中的 encoding="UTF-8" 属性,(不幸的是)导致 .Save() 方法使用 BOM;虽然是多余的,但它也不应该对任何 XML 解析器造成问题。

    • 不幸的是,为了向后兼容,这种冗余行为不会改变 - 请参阅 this GitHub issue

寻址 (a) - 保留原始视觉结构 - 相当简单:

$xmlfile = 'C:\Test\stack.xml'

# Create an empty XmlDocument instance...
$xmlcontent = [xml]::new()
# ... and tell it to preserve non-significant whitespace when 
#     reading from / writing to a file.
$xmlcontent.PreserveWhitespace = $true

# Load the XML text from the file.
$xmlContent.Load($xmlFile)

# ...

# Save it back to the file, with the original whitespace preserved.
$xmlcontent.Save($xmlfile)

注意:以上使用完整文件路径,但在将路径传递给 .NET 方法时始终这样做很重要,因为 .NET 的工作目录通常与 PowerShell 的不同。


如果您确实需要同时处理 (b) 和 (c),请在上述操作之后运行以下

[IO.File]::WriteAllText(
  $xmlfile,
  ((Get-Content -Raw $xmlfile) -replace '(?m)(?<=^<!DOCTYPE .+)\[\](?=>)')
)

【讨论】:

    猜你喜欢
    • 2023-04-11
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    • 2017-12-21
    • 2017-09-09
    • 1970-01-01
    相关资源
    最近更新 更多