I am trying to read a .xml file, change some values (not yet), and write it back out. Without making any changes, I expect to get the same thing comeing out as went in. It does not.
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>
Here is the simple code I am using to read it in and write it out.
PS H:\src\tws> Get-Content .\con000.ps1
$x = [xml](Get-Content -Path .\test000.xml)
$x | Export-Clixml -Path .\con000.xml -Encoding utf8
The output has and sections. Why is that? I would like to get out what went in. I do not care about newlines or the use of HTML entities. I just want the content to be the seme. Yes, the plan is to read a template, change some values, and output a new .xml file. This will be input to the 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><?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>
The purpose of
Export-CliXmlis 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.Its purpose is not to write the text representation of arbitrary
[xml]documents to a file.In order to save a text representation of an
[xml]instance to a file, you have two basic choices:If the specific formatting of the textual representation of the XML document is not a concern, simply call
.OuterXmlon the (modified)[xml]instance and send that to a file - either viaSet-Contentor viaOut-File/>, but note the different default character encodings applied by these cmdlets in Windows PowerShell.Use the .NET framework, if you want a pretty-printed textual representation of the XML in the output file:
The
[xml]type's.Save()method conveniently performs implicit pretty-printing when saving to a file, but there are pitfalls:Since .NET usually has a different idea of what the current directory is, be sure to pass a full file path.
In the absence of an XML declaration with an
encodingattribute, the method creates a UTF-8 file without BOM (which is preferable from a cross-platform perspective).By contrast, curiously, if an XML declaration with
encoding="UTF-8"is present, the resulting file will be UTF-8 with a BOM, as of .NET Core 2.1 / .NET v4.7; see this GitHub issue.Use a
[System.Xml.XmlWriter]instance with an explicitly created file-stream object, which is more cumbersome but gives you control over the specifics of the pretty-printed format.Here's a simple example with
.OuterXml:A note re the use of a BOM (a.k.a. Unicode signature) with UTF-8 and other Unicode encodings:
In Windows PowerShell,
-Encoding utf8invariably creates a BOM (applies not just toSet-Content, but also to other cmdlets that produce file output, such asOut-FileandExport-Csv).PowerShell Core creates BOM-less UTF-8 files by default (and also when you explicitly use
-Encoding utf8); you can opt to have a BOM created with-Encoding utf8BOM.For best overall compatibility, BOMs in UTF-8 files should be avoided: Unix platforms and Unix-heritage utilities also used on Windows Platforms generally don't know how to handle them.
Similarly,
-Encoding UTF7should be avoided, because it is not a standard Unicode encoding (and is written without a BOM in both PowerShell editions).In both PowerShell editions, all other Unicode encodings available with
-Encodingdo create an (encoding-appropriate) BOM:Unicode(UTF-16LE),bigendianunicode(UTF-16BE), andutf32(UTF-32).