Paul Selles
Computers and cats
Tag Archives: Strict Mode
Powershell Tip #1: Strict Mode XML Parsing Gotcha
July 25, 2013
Posted by on I love how easy it is to parse XML with Powershell, but then I started scripting in Strict Mode and got hung-up on a little problem dealing with attributes.
I will revisit a revised cats.xml to use as an example xml file:
<?xml version="1.0" encoding="utf-8"?> <Cats> <Cat Name="Wilson" Type="Tabby"> <Property Name="Fur" Value="Coarse"/> <Property Name="Color" Value="Orange" /> <Part Name="Paws"> <Property Name="Claws" Value="Very sharp" /> </Part> <Part Name="Nose"> <Property Name="Cute" Value="true" /> </Part> </Cat> <Cat Name="Winnie" Type="Short hair"> <Property Name="Fur" Value="Soft"/> <Property Name="Color" Value="Black" /> <Part Name="Paws"> <Property Name="Polydactyl" Value="true" /> <Property Name="Claws" Value="Sharp" /> </Part> <Part Name="Nose"> <Property Name="Cute" Value="true" /> </Part> </Cat> <Cat Name="Luna"> <Property Name="Fur" Value="Soft"/> <Property Name="Color" Value="Black" /> <Part Name="Paws"> <Property Name="Claws" Value="Trimmed" /> </Part> <Part Name="Nose"> <Property Name="Cute" Value="true" /> </Part> </Cat> </Cats>
Lets make a script that will retrieve the Name of a cat by their type:
# Get cat name by type Param ( [ValidateNotNullOrEmpty()] [String]$Type ) [Xml]$Cats = (Get-Content -Path C:\temp\cats.xml) ($Cats.Cats.Cat | Where {$_.Type -match $Type}).Name
The script is nice and short and does what we expect. If the Type matches, it returns the Name of the cat (otherwise, we get nothing):
Now let’s try the script in Strict Mode:
# Get cat name by type Param ( [ValidateNotNullOrEmpty()] [String]$Type ) Set-StrictMode -Version Latest [Xml]$Cats = (Get-Content -Path C:\temp\cats.xml) ($Cats.Cats.Cat | Where {$_.Type -match $Type}).Name
If we try to run the script again we run into problems:
What did we do wrong? As it turns out there are two problems. The first is that the entry for Cat Luna does not have a Type attribute (if we re-ran the tests removing Luna then the script will pass). Secondly, we are expecting Powershell to interpret what we mean by the property Type. We want Type as an attribute name, but how does Powershell know that? This is sloppy scripting, but it works until we switch into Strict Mode.
In order to move forward, we need a better idea of the objects that we are playing with. So let’s get the members of $Cats.Cats.
We can see that this is an System.Xml.XmlElement[1]. We could look the class up or we can intuitively see what method on from the list above will help us clean up our code and test for the attribute Type:
# Get cat name by type Param ( [ValidateNotNullOrEmpty()] [String]$Type ) [Xml]$Cats = (Get-Content -Path C:\temp\cats.xml) $Cat = $Cats.Cats.Cat | Where {$_.GetAttribute('Type') -match $Type} if ($Cat) { $Cat.GetAttribute('Name') }
Using GetAttribute on attribute Type will solve the first error. We solve our second error (when a not matching type is entered) by making sure that the object is not null before reading the attribute Name.
Paul
References
[1] XmlXElement Class. MSDN Library
Recent Comments