如何将.xml读入内存并写出相同的结果



我正在尝试读取一个.xml文件,更改一些值(尚未(,然后将其写回去。在不做任何更改的情况下,我希望得到与进入相同的内容。它没有。

PS H:srctws> type .test000.xml
<?xml version="1.0"?>
<eventRuleSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules"
xsi:schemaLocation="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules/EventRules.xsd">
<eventRule name="PW-TEST001" ruleType="filter" isDraft="no">
<description>Paul's test001</description>
</eventRule>
</eventRuleSet>

这是我用来读入和写出它的简单代码。

PS H:srctws> Get-Content .con000.ps1
$x = [xml](Get-Content -Path .test000.xml)
$x | Export-Clixml -Path .con000.xml -Encoding utf8

输出具有和部分。为什么?我想把进去的东西拿出来。我不关心换行符或 HTML 实体的使用。我只希望内容是精灵。是的,计划是读取模板,更改一些值,然后输出新的.xml文件。这将输入到 IBM/HCS 工作负载调度程序。

PS H:srctws> type .con000.xml
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<XD>&lt;?xml version="1.0"?&gt;&lt;eventRuleSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules" x
si:schemaLocation="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules/EventRules.xsd"&gt;&lt;eventRule
name="PW-TEST001" ruleType="filter" isDraft="no"&gt;&lt;description&gt;Paul's test001&lt;/description&gt;&lt;/eventRule&gt;&lt;/eventRuleSet&gt;</XD>
</Objs>
Export-CliXml的目的是
  • 序列化任意对象以便以后通过Import-CliXml序列化,使用尽力而为的表示来保留特定的输入类型,以便以后通过Import-CliXml"解除冻结"。

  • 其目的不是将任意[xml]文档的文本表示形式写入文件。

要将[xml]实例的文本表示形式保存到文件中,您有两个基本选择:

  • 如果XML 文档的文本表示形式的特定格式不是问题,只需在(修改的([xml]实例上调用.OuterXml并将其发送到文件 - 通过Set-Content或通过Out-File/>,但请注意这些 cmdlet 在 Windows PowerShell 中应用的不同默认字符编码。

  • 如果要在输出文件中对 XML 进行漂亮的打印文本表示,请使用.NET 框架

    • [xml]类型的.Save()方法在保存到文件时可以方便地执行隐式漂亮打印,但存在一些缺陷:

      • 由于 .NET 通常对当前目录有不同的想法,因此请务必传递完整的文件路径

      • 在没有具有encoding属性的 XML 声明的情况下,该方法将创建一个不带 BOM 的UTF-8 文件(从跨平台的角度来看,这是可取的(。

      • 相比之下,奇怪的是,如果存在带有encoding="UTF-8"的XML声明,则生成的文件将是带有BOMUTF-8,从.NET Core 2.1/.NET v4.7开始;请参阅此GitHub问题。

    • [System.Xml.XmlWriter]实例与显式创建的文件流对象一起使用,这更麻烦,但可以控制漂亮打印格式的细节。


下面是一个简单的.OuterXml示例:

# Read the input file into an XML document (in-memory DOM).
$x = [xml] (Get-Content -Raw ./test000.xml)
# Make updates to the in-memory document
$x.eventRuleSet.eventRule.description = 'new description'
# Save the modified document as text to an output file,
# using the un-prettied textual representation provided by the .OuterXml
# property.
# If *BOM-less* UTF-8 encoding is what you want, simply use
#   $x.Save("$PWD/con000.xml")
# In PowerShell *Core*, you'd get BOM-less UTF-8 even with the command below.
$x.OuterXml | Set-Content -Encoding utf8 ./con000.xml

关于使用带有 UTF-8 和其他 Unicode 编码的 BOM(又名 Unicode 签名(的说明:

  • Windows PowerShell中,-Encoding utf8总是创建一个 BOM(不仅适用于Set-Content,还适用于生成文件输出的其他 cmdlet,如Out-FileExport-Csv(。

    • 创建BOM 的 UTF-8 文件需要直接使用 .NET 框架(对于 PowerShell 友好的包装器函数,请参阅我的这个答案(。请注意,.NET 框架的默认编码始终是无 BOM 的 UTF-8。
  • 默认情况下PowerShellCore会创建BOM 的 UTF-8 文件(以及显式使用-Encoding utf8时(;您可以选择使用
    -Encoding utf8BOM创建 BOM。

为了获得最佳的整体兼容性,应避免使用UTF-8文件中的BOM:Windows平台上使用的Unix平台和Unix传统实用程序通常不知道如何处理它们。

同样,应避免-Encoding UTF7,因为它不是标准的 Unicode 编码(并且在两个 PowerShell 版本中都没有 BOM 编写(。

两个PowerShell版本中,-Encoding可用的所有其他Unicode编码都会创建一个(编码适当的(BOM:Unicode(UTF-16LE(,bigendianunicode(UTF-16BE(和utf32(UTF-32(。

在调试器中尝试使用此代码。

$data1 = @"
<?xml version="1.0"?>
<eventRuleSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules"
xsi:schemaLocation="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules/EventRules.xsd">
<eventRule name="PW-TEST001" ruleType="filter" isDraft="no">
<description>Paul's test001</description>
</eventRule>
</eventRuleSet>
"@
$xml1 = [xml]$data1
"`n-------data1"
$data1
"`n--------xml1"
$xml1
"`n--------save to file xml2"
$xml1.Save('d:testxml2.xml')
$file2 = Get-Content 'd:testxml2.xml'
$xml2 = [xml]$file2
"`n--------file2"
$file2
"`n--------edit"
$xml2.eventRuleSet.eventRule.name = "Hello world!"
"`n--------save to file xml3"
$xml2.Save('d:testxml3.xml')
$file3 = Get-Content 'd:testxml3.xml'
"`n--------file3"
$file3

最新更新