如何将 .xml 读入内存并写出相同的结果
How to read .xml into memory and write out the same result
我正在尝试读取 .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 工作负载调度程序。
PS H:\src\tws> type .\con000.xml
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<XD><?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" 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"><eventRule
name="PW-TEST001" ruleType="filter" isDraft="no"><description>Paul's test001</description></eventRule></eventRuleSet></XD>
</Objs>
目的Export-CliXml
is to serialize arbitrary objects for later deserialization via Import-CliXml
, using a best-effort representation with respect to preserving the specific input types for later "rehydration" via Import-CliXml
.
其目的是不是将任意[xml]
文档的文本表示写入文件.
为了将 [xml]
实例的文本表示形式保存到文件中,您有两个基本选择:
如果 XML 文档的文本表示的 特定格式不是问题,只需调用 .OuterXml
(已修改)[xml]
实例并将其发送到文件 - 通过 Set-Content
或通过 Out-File
/ >
,但请注意这些 cmdlet 在 Windows PowerShell.
使用 .NET 框架,如果你想要 a pretty-printed 文本表示输出文件中XML的:
[xml]
type's .Save()
method在保存到文件时方便地执行隐式漂亮打印,但也有缺陷:
由于 .NET 通常对当前目录有不同的理解,因此请务必传递 完整文件路径.
在没有带有 encoding
属性的 XML 声明的情况下,该方法创建一个没有 BOM 的 UTF-8 文件 (从跨平台的角度来看,这是更可取的)。
相比之下,奇怪的是,如果 encoding="UTF-8"
的 XML 声明存在 ,则生成的文件将是 UTF-8 带有 BOM,从 .NET Core 2.1 / .NET v4.7 开始;见 this GitHub issue.
使用带有显式创建的文件流对象的 [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
有关 BOM (a.k.a. Unicode signature) with UTF-8 和其他 Unicode 编码的使用的注释:
在 Windows PowerShell, -Encoding utf8
总是 创建 BOM(不适用仅适用于 Set-Content
,但也适用于产生文件输出的其他 cmdlet,例如 Out-File
和 Export-Csv
).
- 需要直接使用 .NET 框架来创建 BOM-less UTF-8 文件(对于 PowerShell 友好的包装函数,请参阅我的 this answer ).请注意,.NET 框架的默认编码始终是 BOM-less UTF-8。
PowerShell Core 默认创建 BOM-less UTF-8 文件(以及当您明确使用
-Encoding utf8
时);您可以选择使用 -Encoding utf8BOM
.
创建 BOM
为了获得最佳的整体兼容性,应避免使用 UTF-8 文件中的 BOM:Unix 平台和 Unix 继承实用程序也用于 Windows 平台通常不会知道如何处理它们。
同样,应该避免使用 -Encoding UTF7
,因为它不是标准的 Unicode 编码(并且在两个 PowerShell 版本中都没有 BOM 编写)。
在两个 PowerShell 版本中,-Encoding
可用的所有其他 Unicode 编码 do 创建一个(编码适当的)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:\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
我正在尝试读取 .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 工作负载调度程序。
PS H:\src\tws> type .\con000.xml
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<XD><?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" 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"><eventRule
name="PW-TEST001" ruleType="filter" isDraft="no"><description>Paul's test001</description></eventRule></eventRuleSet></XD>
</Objs>
目的
Export-CliXml
is to serialize arbitrary objects for later deserialization viaImport-CliXml
, using a best-effort representation with respect to preserving the specific input types for later "rehydration" viaImport-CliXml
.其目的是不是将任意
[xml]
文档的文本表示写入文件.
为了将 [xml]
实例的文本表示形式保存到文件中,您有两个基本选择:
如果 XML 文档的文本表示的 特定格式不是问题,只需调用
.OuterXml
(已修改)[xml]
实例并将其发送到文件 - 通过Set-Content
或通过Out-File
/>
,但请注意这些 cmdlet 在 Windows PowerShell.使用 .NET 框架,如果你想要 a pretty-printed 文本表示输出文件中XML的:
[xml]
type's.Save()
method在保存到文件时方便地执行隐式漂亮打印,但也有缺陷:由于 .NET 通常对当前目录有不同的理解,因此请务必传递 完整文件路径.
在没有带有
encoding
属性的 XML 声明的情况下,该方法创建一个没有 BOM 的 UTF-8 文件 (从跨平台的角度来看,这是更可取的)。相比之下,奇怪的是,如果
encoding="UTF-8"
的 XML 声明存在 ,则生成的文件将是 UTF-8 带有 BOM,从 .NET Core 2.1 / .NET v4.7 开始;见 this GitHub issue.
使用带有显式创建的文件流对象的
[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
有关 BOM (a.k.a. Unicode signature) with UTF-8 和其他 Unicode 编码的使用的注释:
在 Windows PowerShell,
-Encoding utf8
总是 创建 BOM(不适用仅适用于Set-Content
,但也适用于产生文件输出的其他 cmdlet,例如Out-File
和Export-Csv
).- 需要直接使用 .NET 框架来创建 BOM-less UTF-8 文件(对于 PowerShell 友好的包装函数,请参阅我的 this answer ).请注意,.NET 框架的默认编码始终是 BOM-less UTF-8。
PowerShell Core 默认创建 BOM-less UTF-8 文件(以及当您明确使用
-Encoding utf8
时);您可以选择使用-Encoding utf8BOM
. 创建 BOM
为了获得最佳的整体兼容性,应避免使用 UTF-8 文件中的 BOM:Unix 平台和 Unix 继承实用程序也用于 Windows 平台通常不会知道如何处理它们。
同样,应该避免使用 -Encoding UTF7
,因为它不是标准的 Unicode 编码(并且在两个 PowerShell 版本中都没有 BOM 编写)。
在两个 PowerShell 版本中,-Encoding
可用的所有其他 Unicode 编码 do 创建一个(编码适当的)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:\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