I have this XML document in a text file:
<?xml version="1.0"?> <Objects> <Object Type="System.Management.Automation.PSCustomObject"> <Property Name="DisplayName" Type="System.String">SQL Server (MSSQLSERVER)</Property> <Property Name="ServiceState" Type="Microsoft.SqlServer.Management.Smo.Wmi.ServiceState">Running</Property> </Object> <Object Type="System.Management.Automation.PSCustomObject"> <Property Name="DisplayName" Type="System.String">SQL Server Agent (MSSQLSERVER)</Property> <Property Name="ServiceState" Type="Microsoft.SqlServer.Management.Smo.Wmi.ServiceState">Stopped</Property> </Object> </Objects>
I want to iterate through each object and find the DisplayName
and ServiceState
. How would I do that? I've tried all kinds of combinations and am struggling to work it out.
I'm doing this to get the XML into a variable:
[xml]$priorServiceStates = Get-Content $serviceStatePath;
where $serviceStatePath
is the xml file name shown above. I then thought I could do something like:
foreach ($obj in $priorServiceStates.Objects.Object) { if($obj.ServiceState -eq "Running") { $obj.DisplayName; } }
And in this example I would want a string outputted with SQL Server (MSSQLSERVER)
One way to read an XML document in PowerShell is to typecast a variable to the type [xml]. To create this variable, we can use the Get-Content cmdlet to read all of the text in an XML document. To typecast the output of Get-Content we can simply prepend the text [xml] before the variable.
Casting XML Strings to Objects Another way to use PowerShell to parse XML is to convert that XML to objects. The easiest way to do this is with the [xml] type accelerator. By prefixing the variable names with [xml] , PowerShell converts the original plain text XML into objects you can then work with.
To update the specific XML node using PowerShell, we first need to select that node with the attribute with SelectSingleNode() method. We have below the XML file from the link stored in SampleXml. XML on C:\Temp location. The above commands will load the XML file and select node with attribute value 'bk102'.
PowerShell has built-in XML and XPath functions. You can use the Select-Xml cmdlet with an XPath query to select nodes from XML object and then .Node.'#text' to access node value.
[xml]$xml = Get-Content $serviceStatePath $nodes = Select-Xml "//Object[Property/@Name='ServiceState' and Property='Running']/Property[@Name='DisplayName']" $xml $nodes | ForEach-Object {$_.Node.'#text'}
Or shorter
[xml]$xml = Get-Content $serviceStatePath Select-Xml "//Object[Property/@Name='ServiceState' and Property='Running']/Property[@Name='DisplayName']" $xml | % {$_.Node.'#text'}
You can also do it without the [xml] cast. (Although xpath is a world unto itself. https://www.w3schools.com/xml/xml_xpath.asp)
$xml = (select-xml -xpath / -path stack.xml).node $xml.objects.object.property
Or just this, xpath is case sensitive. Both have the same output:
$xml = (select-xml -xpath /Objects/Object/Property -path stack.xml).node $xml Name Type #text ---- ---- ----- DisplayName System.String SQL Server (MSSQLSERVER) ServiceState Microsoft.SqlServer.Management.Smo.Wmi.ServiceState Running DisplayName System.String SQL Server Agent (MSSQLSERVER) ServiceState Microsoft.SqlServer.Management.Smo.Wmi.ServiceState Stopped
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With