The output you're getting implies that Invoke-RestMethod
worked as intended: it returned a [xml]
(System.Xml.XmlDocument
) instance that is an XML DOM (document object model) of the XML text returned from the site.
Unfortunately, the default display formatting for [xml]
instances, as shown in your question, isn't very helpful[1], but all the information is there, which you can simply verify by accessing the .OuterXml
property:
# Get the XML DOM object parsed from the website's XML text output.
$xml = Invoke-RestMethod 'http://www.aero-news.net/news/rssfeed.xml'
# Output its text representation.
$xml.OuterXml
The above prints a string such as:
<?xml version="1.0" encoding="iso-8859-1"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://purl.org/rss/1.0/">
<channel rdf:about="http://www.aero-news.net">
<title>Aero-News Network</title>
<description>Daily, Real-Time news and information critical to aviation and aerospace personnel the world over. Aero-News provides daily newsletter summaries, RSS feeds, and numerous personal and professional syndication and news distribution options to insure that aviators, the world over, are kept up to date on information of critical concern.</description>
<link>http://www.aero-news.net</link>
...
You can therefore work with the [xml]
(XmlDocument
) instance as usual:
Using PowerShell's convenient adaptation of the XML DOM via property-based dot-notation; e.g., $xml.RDF.channel.about
returns string http://www.aero-news.net
, which is the text content of the about
attribute of the element whose path (from the document root) is /RDF/channel
, irrespective of namespaces[2]; see this answer for more information.
Using the [xml]
type's native properties and methods, such as the XPath-based .SelectNodes()
method for extracting information from the XML document; however, this is less convenient if XML namespaces are involved (such as in your case), because they require explicit management; see this answer for more information.
If you want to pretty-print the XML text:
The [xml]
(System.Xml.XmlDocument
) type doesn't have built-in support for pretty-printing its text content.
While it's possibly to use a System.Xml.XmlWriter
instance, doing so is verbose and cumbersome; however, it does offer you control over the specifics of the pretty-printing format.
A pragmatic, much simpler solution is to use the System.Xml.Linq.XDocument
type instead (for which PowerShell does not provide dot notation, unfortunately), whose .ToString()
method pretty-prints by default, using indentation with two space characters, as the following example demonstrates:
# Create a sample XmlDocument instance, as would be returned
# from an Invoke-RestMethod call (from a site returning XML text):
$xml = [xml] ('<?xml version="1.0"?><catalog><book id="bk101"><title>De Profundis</title></book></catalog>')
# Cast to [System.Xml.Linq.XDocument] via .OuterXml; the former's
# .ToString() method then pretty-prints automatically.
([System.Xml.Linq.XDocument] $xml.OuterXml).ToString()
The above yields the following string:
<catalog>
<book id="bk101">
<title>De Profundis</title>
</book>
</catalog>
Note that the XML declaration is not included, but you can easily prepend it yourself:
$xd = [System.Xml.Linq.XDocument] $xml.OuterXml
$xd.Declaration.ToString() + "`n" + $xd.ToString()
The following Format-Xml
convenience function wraps this functionality:
function Format-Xml {
param(
[Parameter(ValueFromPipeline)]
[xml] $Xml
)
process {
$xd = [System.Xml.Linq.XDocument] $Xml.OuterXml
if ($xd.Declaration) {
$str = $xd.ToString()
$newline = ("`n", "`r`n")[$str.Contains("`r`n")]
$xd.Declaration.ToString() + $newline + $str
}
else {
$xd.ToString()
}
}
}
Now you can use the following to pretty-print the original $xml
variable (obtained via Invoke-RestMethod
):
# Outputs a pretty-printed version of the document's XML text.
$xml | Format-Xml
[1] What is being shown is the content of the document's XML declaration as property .xml
, and the name of the document (root) element as a property named for itself. Printing any given element in the document works as follows: if the element has neither attributes nor child elements, its text content (text child node), if any, is printed. Otherwise, its attributes and their values are printed, followed by properties named for the child elements, each represented by their name as the property value too, if they have attributes and/or child elements themselves, otherwise by their text content, if any.
[2] An example command that processes all feed items whose title contains a given word and transforms them into custom objects.
$userTerm = 'Quote'
$xml.RDF.Item | ? Title -like "*$userTerm*" | % {
[PSCustomObject]@{
Source = "aero"
Title = $_.Title
Link = $_.Link
Description = $_.description
}
}