PowerTip: Use PowerShell to Easily Read an XML Document

PowerTip: Use PowerShell to Easily Read an XML Document

  • Comments 9
  • Likes

Summary: Use the [xml] type accelerator to greatly simplify reading XML documents.

Hey, Scripting Guy! Question How can I easily read an XML file?

Hey, Scripting Guy! Answer Use the [XML] type accelerator to convert results from Get-Content into an XML document, and then use dotted notation to access the nodes:

[xml]$books = Get-Content C:\fso\Books.XML

$books.catalog.book.title

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Ed,

    thanks for sharing....here a proxy function:

    Function Get-Content {

    <#

    ------------EXAMPLE---------------8<-----------------------------------------  

    PS II> $file = "$PSHOME\types.ps1xml"

    PS II> $u = cat $file -As | Select-Xml -XP "//ScriptProperty" | Select -Expand Node

    PS II> $u

    PS II> $Xml = Get-Content $file -AsXml

    PS II> $Xml.Types.Type[1..10]

    ---------------------------8<---------------------AUTHOR: Walid Toumi-------

    .ForwardHelpTargetName Get-Content

    .ForwardHelpCategory Cmdlet

    #>

    [CmdletBinding(DefaultParameterSetName='Path', SupportsTransactions=$true)]

    param(

       [Parameter(ValueFromPipelineByPropertyName=$true)]

       [System.Int64]

       ${ReadCount},

       [Parameter(ValueFromPipelineByPropertyName=$true)]

       [System.Int64]

       ${TotalCount},

       [Parameter(ParameterSetName='Path', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]

       [System.String[]]

       ${Path},

       [Parameter(ParameterSetName='LiteralPath', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]

       [Alias('PSPath')]

       [System.String[]]

       ${LiteralPath},

       [System.String]

       ${Filter},

       [System.String[]]

       ${Include},

       [System.String[]]

       ${Exclude},

       [Switch]

       ${Force},

       [Switch]

       ${AsXml},

       [Parameter(ValueFromPipelineByPropertyName=$true)]

       [System.Management.Automation.PSCredential]

       ${Credential})

    begin

    {

       try {

           $outBuffer = $null

           if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))

           {

               $PSBoundParameters['OutBuffer'] = 1

           }

           $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\Get-Content', [System.Management.Automation.CommandTypes]::Cmdlet)

           $cmd = ''

            if($AsXml) {

             [void]$PSBoundParameters.Remove('AsXml')

             $cmd += ' | ForEach-Object {$fx=@()} {$fx+=$_} {$fx -as [Xml]}'

           }

           $ScriptCmd = [ScriptBlock]::Create(

              { & $wrappedCmd @PSBoundParameters }.ToString() + $Cmd

             )

           $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)

           $steppablePipeline.Begin($PSCmdlet)

       } catch {

           throw

       }

    }

    process

    {

       try {

           $steppablePipeline.Process($_)

       } catch {

           throw

       }

    }

    end

    {

       try {

           $steppablePipeline.End()

       } catch {

           throw

       }

    }

    }

    #########

    PS II> $xml= cat c:\xmlfile.xml -asxml ; $xml

  • @Walid Toumi this is great. Thank you for sharing. Would you consider uploading this to the scripting guys script repository? It would make it eaiser to copy.

  • Very nice. I have used this feature quite often already to import collections / packages / etc. into SCCM, based on an XML input file!

  • I'm using PowerShell 3 and tried your example without the [xml] accelerator and everything seemed to work fine.  What does the accelerator do and is really needed?

  • @Craig the [xml] type accelerator converts the text into an XMLDocument type of object. This permits navigation of the pieces of the document using a dotted notation. Without it, you only have text and not XML. See my article I wrote here: blogs.technet.com/.../use-powershell-to-simplify-access-to-xml-data.aspx

  • @all -

    Note that this will not work if the content is wrapped in a namespace.  To resolve namespaces you will need to either use the namespace manager or use the Select-XML CmdLet with its namespace support.

    I think hear Ed madly typing a blog article on this.

  • Excelente! Simples e direto!!! (Y)

  • hi this is great platform to learn power shell

  • Hey, I'm trying to get specific fields out of an XML files of about 7GB (yes, GB). Using Get-Content and Select-Xml this ends up eating -huge- amounts of memory (70+GB). Hence, I have to find a way to stream the data and process the nodes one by one. I've come across this example, but it seems like this doesn't allow to easily skip entire parts of the XML: https://henry416.wordpress.com/2012/10/05/reading-xml-with-the-xmlreader-in-powershell/

    How would you script this?