Parsing XML with PowerShell

This script allows to parse an XML file.

In this example, the XML must be named config.xml and must be located in the same folder as the script.

The variable $PSScriptRoot is used to retrieve the path where the script is launched.

 

1. Parsing XML – Single Tags and recursively

Let’s create an XML file named “config.xml” in the same location as the script with the following content:

<?xml version="1.0" ?>

<Configuration>	

	<Instrument>Guitare</Instrument>

	<Item ID="1">
		<Manufacturer>Fender</Manufacturer>
		<Model>Stratocaster</Model>
		<Color>Red</Color>
	</Item>

	<Item ID="2">
		<Manufacturer>Gibson</Manufacturer>
		<Model>Les Paul</Model>
		<Color>Black</Color>
	</Item>

</Configuration> 

 

The following script allows to parse the XML:

##*===============================================
##* LOADING XML FILE
##*===============================================

$xml = [xml](Get-Content "$PSScriptRoot\config.xml")



##*===============================================
##* RETRIEVING A SINGLE TAG
##*===============================================

$Instru = $xml.Configuration.Instrument
Write-Host ""
Write-Host "The value of the Instrument tag is $Instru"



##*===============================================
##* RETRIEVING A SINGLE BLOCK : ITEM ID=1
##*===============================================

$Manufacturer = $xml.Configuration.Item | Where-Object {$_.ID -eq '1'} | Select-Object Manufacturer
$Manufacturer = $Manufacturer.Manufacturer
$Model = $xml.Configuration.Item | Where-Object {$_.ID -eq '1'} | Select-Object Model
$Model = $Model.Model
$Color = $xml.Configuration.Item | Where-Object {$_.ID -eq '1'} | Select-Object Color
$Color = $Color.Color
Write-Host ""
Write-Host "Retrieving values of Item where ID=1"
Write-Host "The manufacturer is $Manufacturer"
Write-Host "The model is $Model"
Write-Host "The color is $Color"



##*===============================================
##* RETRIEVING ALL BLOCKS WITH A LOOP
##*===============================================

Write-Host ""
Write-Host "Retrieving values of all Items"
ForEach ($Item in $xml.Configuration.Item) {
    $ItemId = $Item.ID
    Write-Host "Retrieving Item where ID=$ItemId"
    $Manufacturer = $xml.Configuration.Item | Where-Object {$_.ID -eq $ItemId} | Select-Object Manufacturer
    $Manufacturer = $Manufacturer.Manufacturer
    $Model = $xml.Configuration.Item | Where-Object {$_.ID -eq $ItemId} | Select-Object Model
    $Model = $Model.Model
    $Color = $xml.Configuration.Item | Where-Object {$_.ID -eq $ItemId} | Select-Object Color
    $Color = $Color.Color
    Write-Host "The manufacturer is $Manufacturer"
    Write-Host "The model is $Model"
    Write-Host "The color is $Color"
}



##*===============================================
##* CHECKING DUPLICATE ITEM ID
##*===============================================

Write-Host ""
Write-Host "Check duplicate ID in XML" 
$duplicate=0
For([int] $i=0;$i -lt $xml.Configuration.Item.count;$i++) {
    For([int] $j=$i+1;$j -lt $xml.Configuration.Item.count;$j++) {
        If($xml.Configuration.Item[$i].id  -eq $xml.Configuration.Item[$j].id) {
            $duplicate=1
        }
    }
}
If ($duplicate -eq 0) {
    Write-Host "OK - no duplicate Item ID in XML"
}
Else {
    Write-Host "Error - Duplicate Item ID found in XML"
} 

 

2. Parsing XML – Looping a Loop

The goal here is to retrieve data of a loop inside another loop.

Let’s create an XML file named “config.xml” with the following content:

<?xml version="1.0" ?>

<Configuration>	

	<COUNTRY NAME="SWITZERLAND">
		
		<Place ID="1">
			<City>Geneva</City>
			<NbUsers>120</NbUsers>
            <NbMachines>150</NbMachines>
		</Place>

        <Place ID="2">
			<City>Lausanne</City>
			<NbUsers>50</NbUsers>
            <NbMachines>75</NbMachines>
		</Place>
		
	</COUNTRY>

    <COUNTRY NAME="FRANCE">
		
		<Place ID="1">
			<City>Paris</City>
			<NbUsers>100</NbUsers>
            <NbMachines>110</NbMachines>
		</Place>

        <Place ID="2">
			<City>Lille</City>
			<NbUsers>20</NbUsers>
            <NbMachines>25</NbMachines>
		</Place>

        <Place ID="3">
			<City>Dunkerque</City>
			<NbUsers>2</NbUsers>
            <NbMachines>3</NbMachines>
		</Place>
		
	</COUNTRY>

    <COUNTRY NAME="USA">
		
		<Place ID="1">
			<City>New-York</City>
			<NbUsers>200</NbUsers>
            <NbMachines>400</NbMachines>
		</Place>

        <Place ID="2">
			<City>Boston</City>
			<NbUsers>150</NbUsers>
            <NbMachines>180</NbMachines>
		</Place>
		
	</COUNTRY>

</Configuration>

 

The following script allows to parse the XML, retrieving dynamically the data using 2 loops.

##*===============================================
##* LOADING XML FILE
##*===============================================

$xml = [xml](Get-Content "$PSScriptRoot\config.xml")



##*===============================================
##* LOOPING A LOOP
##*===============================================

ForEach ($COUNTRY in $xml.Configuration.COUNTRY) {
    $COUNTRYNAME = $COUNTRY.NAME
    Write-Host "$COUNTRYNAME"
    Write-Host ""
    
    $WaveCount = $SOE.Wave.count

    ForEach ($Place in $COUNTRY.Place) {
        $PlaceID = $Place.ID
        $City = $COUNTRY.Place | Where-Object {$_.ID -eq $PlaceID} | Select-Object City
        $City = $City.City
        Write-Host "Place $PlaceID is $City"

        $NbUsers = $COUNTRY.Place | Where-Object {$_.ID -eq $PlaceID} | Select-Object NbUsers
        $NbUsers = $NbUsers.NbUsers
        Write-Host "NbUsers is $NbUsers"

        $NbMachines = $COUNTRY.Place | Where-Object {$_.ID -eq $PlaceID} | Select-Object NbMachines
        $NbMachines = $NbMachines.NbMachines
        Write-Host "NbMachines is $NbMachines"

        Write-Host ""
    }
    Write-Host ""
}