1

我正在尝试读取 .xml 文件,更改一些值(尚未),然后将其写回。在不进行任何更改的情况下,我希望得到与进入时相同的内容。但事实并非如此。

PS H:\src\tws> 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:\src\tws> Get-Content .\con000.ps1
$x = [xml](Get-Content -Path .\test000.xml)
$x | Export-Clixml -Path .\con000.xml -Encoding utf8

输出有 和 部分。这是为什么?我想知道里面的内容。我不关心换行符或 HTML 实体的使用。我只想让内容成为精髓。是的,计划是读取一个模板,更改一些值,然后输出一个新的 .xml 文件。这将输入到 IBM/HCS Workload Scheduler。

PS H:\src\tws> 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>
4

2 回答 2

4
  • 的目的Export-CliXml序列化任意对象以供以后通过反序列Import-CliXml化,使用关于保留特定输入类型以供以后通过“再水化”的最佳努力表示Import-CliXml

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

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

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

  • 使用.NET framework,如果您想要输出文件中 XML漂亮打印文本表示:

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

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

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

      • 相比之下,奇怪的是,如果存在 XML 声明,encoding="UTF-8" 生成的文件将是带有BOM 的 UTF-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)。

    • 需要直接使用 .NET 框架来创建无 BOMUTF-8 文件(对于 PowerShell 友好的包装函数,请参阅我的这个答案)。请注意,.NET 框架的默认编码一直是无 BOM 的 UTF-8。
  • PowerShell Core默认创建无 BOMUTF-8 文件(以及当您明确使用时);您可以选择使用.
    -Encoding utf8-Encoding utf8BOM

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

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

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

于 2018-10-26T02:36:21.283 回答
0

在调试器中使用此代码。

$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:\test\xml2.xml')

$file2 = Get-Content 'd:\test\xml2.xml'
$xml2 = [xml]$file2

"`n--------file2"
$file2

"`n--------edit"
$xml2.eventRuleSet.eventRule.name = "Hello world!"

"`n--------save to file xml3"
$xml2.Save('d:\test\xml3.xml')

$file3 = Get-Content 'd:\test\xml3.xml'

"`n--------file3"
$file3
于 2018-10-26T03:18:29.803 回答