2

I'm executing an HTTP Get request (via Invoke-WebRequest) against a website, that's in turn, is returning the following XML structure:

<?xml version="1.0" encoding="utf-8"?>
<ROOT xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <VENDOR>
    <SUBJECT>Check Oil</SUBJECT>
    <VENDORID>NA</VENDORID>
    <VANTIVE>2</VANTIVE>
    <MODEL>I</MODEL>
    <DESCRIPTION>Success</DESCRIPTION>
  </VENDOR>
  <VENDOR>
    <SUBJECT>Check Lights</SUBJECT>
    <SIGN>N</SIGN>
    <VENDORID>NA</VENDORID>
    <VANTIVE>2</VANTIVE>
    <MODEL>I</MODEL>
    <DESCRIPTION>Success</DESCRIPTION>
  </VENDOR>
  <VENDOR>
    <SUBJECT>Check Engine</SUBJECT>
    <SIGN>N</SIGN>
    <VENDORID>NA</VENDORID>
    <VANTIVE>2</VANTIVE>
    <MODEL>I</MODEL>
    <DESCRIPTION>Success</DESCRIPTION>
  </VENDOR>
</ROOT> 

When trying to parse the XML data, using the ConvertTo-Xml cmdlet:

$result = Invoke-WebRequest -Uri 'https://mycars.com/list/cars' -UseBasicParsing -Method Get

$resultinxml = $result.Content | ConvertTo-Xml 
 
$resultinxml.Objects.Object.'#text' 

Everything is working properly.

But when I'm trying to use the [xml] accelerator type instead:

$result = Invoke-WebRequest -Uri 'https://mycars.com/list/cars' -UseBasicParsing -Method Get

[xml] $resultinxml = $result.Content

The following error is occurred:

Cannot convert value "<?xml version="1.0" encoding="utf-8"?>
<ROOT xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <VENDOR>
    <SUBJECT>Check Oil</SUBJECT>
    <VENDORID>NA</VENDORID>
    <VANTIVE>2</VANTIVE>
    <MODEL>I</MODEL>
    <DESCRIPTION>Success</DESCRIPTION>
  </VENDOR>
  <VENDOR>
    <SUBJECT>Check Lights</SUBJECT>
    <SIGN>N</SIGN>
    <VENDORID>NA</VENDORID>
    <VANTIVE>2</VANTIVE>
    <MODEL>I</MODEL>
    <DESCRIPTION>Success</DESCRIPTION>
  </VENDOR>
  <VENDOR>
    <SUBJECT>Check Engine</SUBJECT>
    <SIGN>N</SIGN>
    <VENDORID>NA</VENDORID>
    <VANTIVE>2</VANTIVE>
    <MODEL>I</MODEL>
    <DESCRIPTION>Success</DESCRIPTION>
  </VENDOR>
</ROOT> 
" to type "System.Xml.XmlDocument". Error: "The specified node cannot be inserted as the valid child of this node, because the specified node is the wrong type."
At line:1 char:1
+ $webreqcontent = [xml] ($result.Content)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastToXmlDocument

Which is very odd, as the XML structure hasn't been changed and is XML valid.

Do accelerator types in PowerShell has some prerequisites or limitations, that could cause this issue?

edwio
  • 198
  • 3
  • 20
  • Does the same happen if trying this way `($xml = [xml]::new()).Load($result.Content)` ? – Santiago Squarzon Feb 22 '23 at 13:36
  • @SantiagoSquarzon, I'm getting the following error: `($xml = [xml]::new()).Load($result.Content) Exception calling "Load" with "1" argument(s): "Illegal characters in path." At line:1 char:2 + ($xml = [xml]::new()).Load($result.Content) + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException` – edwio Feb 22 '23 at 13:43
  • I meant `.LoadXml($result.Content)` in my previous comment. Still, the issue seems to be related to encoding – Santiago Squarzon Feb 22 '23 at 13:46
  • @SantiagoSquarzon, returning a different error: `($xml = [xml]::new()).LoadXML($result.Content) Exception calling "LoadXml" with "1" argument(s): "Data at the root level is invalid. Line 1, position 1." At line:1 char:2 + ($xml = [xml]::new()).LoadXML($result.Content) + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException `can you please elaborate regarding the Unicode? i'm 100% sure that the XML is valid. – edwio Feb 22 '23 at 13:50
  • Have a look here https://stackoverflow.com/a/27743515/15339544. If you want you could try `$result.Content | Format-Hex` and add the results to your question – Santiago Squarzon Feb 22 '23 at 14:02
  • 2
    ```$myXmlText | ConvertTo-Xml``` isn't the same as ```[xml] $myXmlText``` - ```ConvertTo-Xml``` converts an object model **into** xml text, rather than **parse** xml text into objects like ```[xml]``` does. Try this on the command line and you'll see a hot mess of escaped xml junk: ```("" | ConvertTo-Xml).OuterXml``` – mclayton Feb 22 '23 at 14:21

1 Answers1

1

Building on the helpful comments on the question:

When trying to parse the XML data, using the ConvertTo-Xml cmdlet:

ConvertTo-Xml does not parse XML, it creates XML representations (serialization) of arbitrary .NET instances - and since the resulting XML format is neither documented nor is there a complementary cmdlet to interpret (deserialize) it, this cmdlet is virtually useless - see GitHub issue #8311.
GitHub issue #3898 is a green-lit proposal to introduce ConvertTo-CliXml and ConvertFrom-CliXml cmdlets, instead, which will use the standardized CLIXML format that PowerShell uses for cross-process serialization, such as in remoting.

In other words: your use of ConvertTo-Xml won't work as intended.


If you use Invoke-RestMethod instead of Invoke-WebRequest, XML parsing is built in (with web services that return XML) and directly returns a [xml] (System.Xml.XmlDocument) instance.

# If the web-service call returns XML, Invoke-RestMethod automatically
# parses it into a [xml] instance.
$resultXml = Invoke-RestMethod -Uri 'https://mycars.com/list/cars' 

However, your error message suggests that you have one or more extraneous characters preceding the XML text - even though, curiously, that isn't reflected in the error message, at least as shown in your question.

  • A simple way to provoke the error is with [xml] '!<foo/>'

Conceivably, the XML text is preceded by a BOM (byte order mark), even though it normally shouldn't in this context.

  • If that is the problem, you can try the following:
$result = Invoke-WebRequest -Uri 'https://mycars.com/list/cars' -UseBasicParsing

# Skip the BOM character .
[xml] $resultinxml = $result.Content.Substring(1)
  • If it isn't, you'll need to examine the XML text for hidden control characters, as shown in this answer.

A solution to a related problem - an XML response getting misinterpreted due to a character-encoding mismatch - can be found in this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775