2

I have a Powershell script which calls an XML, gets a URL, and tries to open Chrome to that URL. Downside, the URL contains the = character, and none of the character escape suggestions I've seen work.

Here's the XML:

<Config>
    <Stuff>
        <Application Name="Place" CaptivePortal="https://website.com:1337/php/uid.php?thing=1&stuff=0" RDP="192.168.1.1" Entitlement="Admin" />
    </Stuff>
</Config>

And here's the section of the PS scripts that's calling it:

Function func_launch_Stuff($v_func_parm_launch_type, $v_func_parm_launch_element){

    # launch based on type
    switch ($v_func_parm_launch_type)
    {
        "URL" {
            $v_Application_Launch = "C:\Program Files\Google\Chrome\Application\chrome.exe"
            $v_Application_Argument = "$($v_func_parm_launch_element)"
            Start-Process -FilePath $v_Application_Launch -ArgumentList $v_Application_Argument -Wait}
}
}

[xml]$v_XML_Config_File = Get-Content -Path $v_parm_XML_Config_File

I've trimmed out other sections, because this is the only one throwing errors. I'd go into changing the original script more, but it was hand crafted by an engineer we don't have anymore, and I'm not good enough with PS to redo this myself in a way that'll handle my issue without making 10 more.

I've tried using the four options from here, and manually replacing the = character with =. It always throws the error below, with X replaced by =, `=, or &.

"Error message: Cannot convert value "System.Object[]" to type "System.Xml.XmlDocument". Error: "'X' is an unexpected token."

mklement0
  • 382,024
  • 64
  • 607
  • 775

2 Answers2

3

Your XML is malformed:

  • It contains an unescaped & character (&stuff=0), which is the cause of your problem: what follows it is considered part of an XML entity reference, and since & is not the start of one in your document, parsing breaks, namely when the = is encountered (given that = isn't a legal character in the name of an entity reference).

  • Replace & with &amp; - i.e. the entity reference that represents a literal & - and your problem goes away:

# OK, because "&" was escaped as "&amp;"
[xml] @'
<Config>
    <Stuff>
        <Application Name="Place" CaptivePortal="https://website.com:1337/php/uid.php?thing=1&amp;stuff=0" RDP="192.168.1.1" Entitlement="Admin" />
    </Stuff>
</Config>
'@

If you cannot fix the problem at the source, perform a string replacement (using a simplified example):

# Replace '&' with '&amp;' before casting to [xml]
[xml] (@'
  <Config>
    <Foo Url="https://example.org?foo&bar"/>
  </Config>
'@).Replace('&', '&amp;')

Note: This simple approach assumes that your document does not contain & characters that are part of valid entity references already. You'd need a more sophisticated approach, using regexes to handle that case.


As an aside re parsing XML from files:

 [xml]$v_XML_Config_File = Get-Content -Path $v_parm_XML_Config_File
  • You can speed up your command by adding -Raw to the Get-Content call, which causes it to read the entire file as a whole.

  • However, this - convenient - approach is not fully robust, as Get-Content may misinterpret the character encoding of your input file.

    • A fully robust (but less convenient) solution is:

      ($v_XML_Config_File = [xml]::new()).Load((Convert-Path $v_parm_XML_Config_File))
      
    • See the bottom section of this answer for details.

mklement0
  • 382,024
  • 64
  • 607
  • 775
-3

Your last line in sample code should be changed...

From:

[xml]$v_XML_Config_File = Get-Content -Path $v_parm_XML_Config_File

To:

[xml]$v_XML_Config_File = Get-Content -Path $v_parm_XML_Config_File | ConvertTo-Xml

I've tested sample xml which you posted and got errors, by piping to ConverTo-Xml it worked.

metablaster
  • 1,958
  • 12
  • 26
  • 1
    The rarely used [`ConvertTo-Xml`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/convertto-xml) is _not_ meant for XML parsing; instead, it takes arbitrary input objects and creates an XML representation for them. Therefore, in your case you'll end up with an XML document with an entirely different strucutre. /cc @MerlinTheWizard – mklement0 Dec 14 '22 at 19:12
  • Well, that'd explain why it now fails to read the **Entitlement** section in the original XML. Any idea how to get the = character working in the original XML without breaking the rest of the XML? – Merlin The Wizard Dec 14 '22 at 19:20
  • @MerlinTheWizard, you must escape `&` as `&`, as discussed in my answer. – mklement0 Dec 14 '22 at 19:22
  • 1
    @mklement0 that's fine, I should have focused on the xml rather than sample code. – metablaster Dec 15 '22 at 08:54