Parsing XML data using import-clixml cmdlet

Hi there!

I am pretty new to Powershell and am working on a project where I need to have a comparison between 2 different XML files (which contain exported policies from from 2 different Citrix farms). The aim is to check the consistency between the 2 Citrix farms in terms of policies which are applied, by comparing the two XML files.

The XML output is large. I have tried using both Xpath and import-clixml cmdlets to look into the data.

If I run
[xml]$xmldoc=Get-Content
$xmldoc.documentelement.obj.ms.obj.ms.s
I get the following:
N #text


State NotConfigured
Path XMLService\TrustXmlRequests
State NotConfigured
Value 0
Path XMLService\XmlServicePort
State NotConfigured
Path VirtualIP\EnhancedCompatibility
State NotConfigured
Path VirtualIP\EnhancedCompatibilityPrograms
State NotConfigured
Path VirtualIP\FilterAdapterAddresses
State NotConfigured
Path VirtualIP\FilterAdapterAddressesPrograms
State NotConfigured
Path VirtualIP\VirtualLoopbackPrograms
State NotConfigured
Path VirtualIP\VirtualLoopbackSupport
State NotConfigured
Value 80
Path VirtualDesktopAgent\ControllerRegistrationPort
State NotConfigured
Value
Path VirtualDesktopAgent\Controllers
State NotConfigured
Value
Path VirtualDesktopAgent\ControllerSIDs
State NotConfigured
Value
Path VirtualDesktopAgent\SiteGUID
State NotConfigured
Path VirtualDesktopAgent\CPUUsageMonitoring\CPUUsageMonitoring_Enable
State NotConfigured
Value 60
Path VirtualDesktopAgent\CPUUsageMonitoring\CPUUsageMonitoring_Period
State NotConfigured
Value 95
Path VirtualDesktopAgent\CPUUsageMonitoring\CPUUsageMonitoring_Threshold
State NotConfigured
Value AllowAny
Path ServerSettings\ConnectionAccessControl
State NotConfigured
Path ServerSettings\DnsAddressResolution
State NotConfigured
Path ServerSettings\FullIconCaching
State NotConfigured
Value Default Zone
Path ServerSettings\InitialZone

Now if I try to;
$xmldoc.documentelement.obj.ms.obj.ms.s | where {$_."#text" -eq “enabled”}
I get:
N #text


State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled
State Enabled

Using the Import-CliXML cmdlet:
$xml = Import-Clixml
Now if I see the output, it shows as :
$xml

PolicyName : Policy Name Here
Type : Computer
TrustXmlRequests : @{State=NotConfigured; Path=XMLService\TrustXmlRequests}
XmlServicePort : @{State=NotConfigured; Value=0; Path=XMLService\XmlServicePort}
EnhancedCompatibility : @{State=NotConfigured; Path=VirtualIP\EnhancedCompatibility}
EnhancedCompatibilityPrograms : @{State=NotConfigured; Path=VirtualIP\EnhancedCompatibilityPrograms}
FilterAdapterAddresses : @{State=NotConfigured; Path=VirtualIP\FilterAdapterAddresses}
FilterAdapterAddressesPrograms : @{State=NotConfigured; Values=System.Collections.ArrayList;
Path=VirtualIP\FilterAdapterAddressesPrograms}
VirtualLoopbackPrograms : @{State=NotConfigured; Path=VirtualIP\VirtualLoopbackPrograms}
VirtualLoopbackSupport : @{State=NotConfigured; Path=VirtualIP\VirtualLoopbackSupport}
ControllerRegistrationPort : @{State=NotConfigured; Value=80; Path=VirtualDesktopAgent\ControllerRegistrationPort}
Controllers : @{State=NotConfigured; Value=; Path=VirtualDesktopAgent\Controllers}
ControllerSIDs : @{State=NotConfigured; Value=; Path=VirtualDesktopAgent\ControllerSIDs}
SiteGUID : @{State=NotConfigured; Value=; Path=VirtualDesktopAgent\SiteGUID}
CPUUsageMonitoring_Enable : @{State=NotConfigured; Path=VirtualDesktopAgent\CPUUsageMonitoring\CPUUsageMonitoring_Enable}
CPUUsageMonitoring_Period : @{State=NotConfigured; Value=60;
Path=VirtualDesktopAgent\CPUUsageMonitoring\CPUUsageMonitoring_Period}
CPUUsageMonitoring_Threshold : @{State=NotConfigured; Value=95;
Path=VirtualDesktopAgent\CPUUsageMonitoring\CPUUsageMonitoring_Threshold}

Now all policies show as Properties under get-member cmdlet. How can I extract the fields which have the “State” as not equal to “Not configured” or in other words where “State” is “enabled”?

Probably something like this:

$xml.PSObject.Properties |
Where-Object { $_.Value.State -eq 'Enabled' } |
Select-Object Name, @{ Name = 'State'; Expression = { $_.Value.State } }

Thanks for the response Dave.

When I run this command, it does not give me any output. When I tried with breaking down the command I get the following:

PS> $xml.psobject.Properties

ReferencedMemberName : Length
ConversionType :
MemberType : AliasProperty
TypeNameOfValue : System.Int32
IsSettable : False
IsGettable : True
Value : 17
Name : Count
IsInstance : False

MemberType : Property
Value : 17
IsSettable : False
IsGettable : True
TypeNameOfValue : System.Int32
Name : Length
IsInstance : True

MemberType : Property
Value : 17
IsSettable : False
IsGettable : True
TypeNameOfValue : System.Int64
Name : LongLength
IsInstance : True

MemberType : Property
Value : 1
IsSettable : False
IsGettable : True
TypeNameOfValue : System.Int32
Name : Rank
IsInstance : True

MemberType : Property
Value : {@{PolicyName=POLICY NAME HERE; Type=Computer; TrustXmlRequests=; XmlServicePort=;
EnhancedCompatibility=; EnhancedCompatibilityPrograms=; FilterAdapterAddresses=; FilterAdapterAddressesPrograms=;
VirtualLoopbackPrograms=; VirtualLoopbackSupport=; ControllerRegistrationPort=; Controllers=; ControllerSIDs=; SiteGUID=;
CPUUsageMonitoring_Enable=; CPUUsageMonitoring_Period=; CPUUsageMonitoring_Threshold=; ConnectionAccessControl=;
DnsAddressResolution=; FullIconCaching=; InitialZone=; LoadEvaluator=; ProductEdition=; ProductModel=;
RebootCustomMessage=; RebootCustomMessageText=; RebootDisableLogOnTime=; RebootScheduleFrequency=;
RebootScheduleRandomizationInterval=; RebootScheduleStartDate=; RebootScheduleTime=; RebootWarningInterval=;
RebootWarningMessage=; RebootWarningStartTime=; ScheduledReboots=; OfflineClientTrust=; OfflineEventLogging=;
OfflineLicensePeriod=; OfflineUsers=; CpuManagementServerLevel=; MemoryOptimization=; MemoryOptimizationDayOfMonth=;
MemoryOptimizationDayOfWeek=; MemoryOptimizationExcludedPrograms=; MemoryOptimizationIntervalType=;
MemoryOptimizationTime=; HealthMonitoring=; HealthMonitoringTests=; MaximumServersOfflinePercent=; InitialDatabaseName=;
InitialDatabaseServerName=; InitialFailoverPartner=; UserSessionLimit=; UserSessionLimitAffectsAdministrators=;
UserSessionLimitLogging=; FarmName=; WorkloadName=; LicenseServerHostName=; LicenseServerPort=; IcaListenerPortNumber=;
IcaListenerTimeout=; AcceptWebSocketsConnections=; WebSocketsPort=; WSTrustedOriginServerList=; Shadowing=;
SessionReliabilityConnections=; SessionReliabilityPort=; SessionReliabilityTimeout=; IdleTimerInterval=;
PromptForPassword=; UpsCgpPort=; UpsEnable=; UpsHttpPort=; MultimediaAcceleration=;
MultimediaAccelerationDefaultBufferSize=; MultimediaAccelerationUseDefaultBufferSize=; MultimediaConferencing=;
MultiPortPolicy=; MultiStreamPolicy=; RtpAudioPortRange=; IcaKeepAlives=; IcaKeepAliveTimeout=; DisplayDegradePreference=;
DisplayDegradeUserNotification=; DisplayMemoryLimit=; DynamicPreview=; ImageCaching=; MaximumColorDepth=;
QueueingAndTossing=; PersistentCache=; IcaRoundTripCalculation=; IcaRoundTripCalculationInterval=;

I do not get the state property in the output, thus again when I run
PS>$xml.psobject.Properties | Where-Object {$_.value.state -eq ‘enabled’}
the output is blank.

I have tried setting $xml as follows, the output of the above command remains null:

  1. $xml = import-clixml (XML file path)
  2. [xml]$xml = Get-content (XML file path)

Is there something that I need to do differently?

Object probably isn’t of the type that it appeared to be from the output. Can you put the CliXml into a Gist? Our forum software treats XML tags like HTML and you wind up losing all of the important bits.

https://gist.github.com/anonymous/137d5000f5412310ebaae956f539e9db

I meant the contents of the XML file, not the output you get after importing it. :slight_smile:

https://gist.github.com/anonymous/f6d13d299de85fa520e9f50d235bf369

Hmm… don’t think the content was completely posted. I had to close the Objs tag manually at the end, and when it did, the code I posted worked fine. However, based on what you posted earlier, I suspect that your $xml variable is an array or collection of some sort, rather than a single object. For that, try this:

$xml | ForEach-Object {
    $_.PSObject.Properties |
    Where-Object { $_.Value.State -eq 'Enabled' } |
    Select-Object Name, @{ Name = 'State'; Expression = { $_.Value.State } }
}

That worked like a charm!

Thanks for all the help Dave!
/Cheers\