1

I have a sample XML file test.xml that looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Response>
  <Update>
    <foo>1.1.1</foo>
    <bar>12345</bar>
  </Update>
</Response>

I'm trying to use PowerShell to get the value of foo. I can download and save the file into text.xml and then access foo. This works:

Invoke-RestMethod $myurl | Out-File test.xml
[xml]$abc = (Get-Content test.xml) 
$abc.Response.Update.foo

However, I receive errors when I attempt to save the XML content into the $abc variable like this:

[xml]$abc = (Invoke-RestMethod $myurl)

Error:

MetadataError: Cannot convert value "<?xml version="1.0" encoding="utf-8"?>
<Response>
  <Update>
[...snip...]
  </Update>
</Response>" 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."

What am I doing wrong here?

Update #1

This produces no output and no errors:

$abc = Invoke-RestMethod $myurl
$abc.Response
$abc.Response.Update           
$abc.Response.Update.foo

Changing to Invoke-WebRequest:

[xml]$abc = Invoke-WebRequest $myurl

Error is the same, but now there is three question marks in the beginning. So it's possible that the problem is somehow related to the file's encoding.

MetadataError: Cannot convert value "???<?xml version="1.0" encoding="utf-8"?>
<Response>
  <Update>
[...snip...]
  </Update>
</Response>" 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."
bahrep
  • 29,961
  • 12
  • 103
  • 150
  • Maybe `$abc = [xml] $(Invoke-RestMethod $myurl)`? – JosefZ Jan 21 '23 at 20:30
  • What properties does invoke-restmethod return? You probably only want something like the .content property. – js2010 Jan 22 '23 at 00:19
  • @JosefZ This command fails with the same error. – bahrep Jan 22 '23 at 08:04
  • 2
    `Invoke-RestMethod` normally already returns an `[xml]` instance for you. Thus, if you omit the `[xml]` cast / type constraint, do you get the same error? If so, use `Invoke-WebRequest` instead, and examine the `.Content` property, which should contain the response _as plain text_. This might provide a clue as to why parsing as XML fails. – mklement0 Jan 22 '23 at 14:47
  • @mklement0 Thank you. `$abc = Invoke-RestMethod $myurl` and `$abc.Response.Update.foo` don't produce any output (and no errors). I've just updated the question with other new details. – bahrep Jan 22 '23 at 15:29
  • 1
    What does $abc produce? Maybe invoke-webrequest gets a bom in the beginning. – js2010 Jan 22 '23 at 15:42
  • @js2010 `[xml]$abc.Content InvalidArgument: Cannot convert value " ... ` – bahrep Jan 22 '23 at 15:44
  • `[xml]$abc InvalidArgument: Cannot convert value "??? ...` – bahrep Jan 22 '23 at 15:44
  • try with `($xml = [xml]::new()).Load((Invoke-RestMethod $myurl))` – Santiago Squarzon Jan 23 '23 at 03:32

2 Answers2

1

Your symptom suggests that there are three unrecognized characters preceding the XML text returned by your web service.

  • While three characters could generally indicate what constitutes a mis-decoded UTF-8 (pseudo) BOM,
    • (a) such a BOM is usually only present in files on disk, not in web-service responses
    • (b) even if it were mis-decoded as the default encoding used by the web cmdlets up to PowerShell 7.2.x, ISO-8859-1, it would print as , not as ???

Pragmatically speaking, assuming that the remaining text is properly decoded, you can simply skip the three characters as follows:

[xml] (Invoke-WebRequest $myUrl).Content.Substring(3)

If that doesn't help, use a text editor to examine the downloaded file and determine its de-facto encoding, then try to decode the raw bytes as a string with that encoding, as shown in this answer.

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

Using Xml Linq :

using assembly System.Xml.Linq 

$xml = @"
<?xml version="1.0" encoding="utf-8"?>
<Response>
  <Update>
    <foo>1.1.1</foo>
    <bar>12345</bar>
  </Update>
</Response>
"@
$doc = [System.Xml.Linq.XDocument]::Parse($xml)
$update = $doc.Descendants("Update").Foreach([System.Xml.Linq.XElement])
$foo = $update.Element("foo").Value
$bar = $update.Element("bar").Value
Write-Host "foo = " $foo "bar = " $bar
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • 1
    You're showing a different solution to something that not only the OP already knows how to do, but knows how to do more simply (`[xml]$abc = (Get-Content test.xml)`). This question isn't about XML-parsing techniques, but about possible encoding problems. Your answer doesn't address the problem at hand and introduces incidental information without an explanation. In short: your answer is likely to be an unhelpful distraction to future readers. – mklement0 Jan 23 '23 at 16:40
  • @mklement0 : There is nothing wrong with the file and there is no encoding issues. – jdweng Jan 23 '23 at 16:53