Search code examples
xmlpowershelllineedit

Edit Single Line XML File In PowerShell Without Changing to Multi-Line XML File


I have a HUGE XML file that has a whole ton of data packed into a single line. I've found when I edit that file with PowerShell, it breaks all of the data up into individual lines instead of a single line. Initially it was changing the encoding from UTF-8 to UTF-8 BOM so I thought that might be the culprit. I've since fixed that portion of my script and made sure it's still saving as UTF-8 without BOM, but everything is still getting converted from one line to over 600 lines after I run my script.

Anyone know any tricks to keep the formatting on single line xml files when editing in PowerShell?


Solution

  • Assuming that your XML file still fits into memory as an [xml] (System.Xml.XmlDocument) DOM:

    • When you pass a file path to the .Save() method, pretty-printing of the XML is performed by default.

    • To modify this default behavior you must construct a System.Xml.XmlWriter instance based on a custom System.Xml.XmlWriterSettings instance that gives you control over the serialization behavior.

      • In fact, such settings default to not pretty-print, and would require setting the .Indent property to $true for pretty-printing.
      • You can also use the .Encoding property in order to specify a BOM-less UTF-8 encoding, as is your intent.

    Here's a self-contained example:

    # Sample input XML
    [xml] $xml = '<?xml version="1.0"?><catalog><book id="bk101"><title>De Profundis</title></book></catalog>'
    
    # Create a non-pretty-printing XmlWriter instance 
    # with BOM-less UTF-8 encoding that will write to file "test.xml"
    # in the current directory.
    $writer = [System.Xml.XmlWriter]::Create(
      "$PWD/test.xml", # IMPORTANT: Use a FULL PATH here, because .NET's working dir. usually differs from PowerShell's
      [System.Xml.XmlWriterSettings] @{ Encoding = [Text.UTF8Encoding]::new() }
    )
    
    try {
      # Save the document via the writer.
      $xml.Save($writer)
    } finally {
      # (Close and) dispose of the writer.
      $writer.Dispose()
    }