Powershell getting node values of different levels in one Select-Object

Viewed 348

Is there a way to do a Select-Object and get the values of nodes of different levels?

I need the name and a bunch of fields from the field level but also the globalFormat categoryType. Is there a way to have them in one Select-Object?

XML

<field name="FLD0000001" tableAlias="*SERVER" tableName="*SERVER">
  <order>0</order>
  <version></version>
  <afterEditEvent></afterEditEvent>
  <format></format>
  <globalFormat categoryType="Number" countrySymbolCode="" dateFormat="" timeFormat="" imageFormat="None" decimalPlaces="2" leadingZero="0" isCentury="false" negativeFormat="NegativeSymbol" />
  <columnGroupHeading></columnGroupHeading>
  <dataFieldType>20</dataFieldType>
  <columnHeading><![CDATA[FLD0000001]]></columnHeading>
  <hideHeader>False</hideHeader>
  <groupable>0</groupable>
  <subTotal>0</subTotal>
  <calculation></calculation>
  <jScriptCalculation />
  <editCalculation scriptContent="" scriptDisplayContent="">
    <tokens />
    <triggers />
  </editCalculation>
  <onCalculationEvent></onCalculationEvent>
  <onValidationEvent></onValidationEvent>
  <editableAdvanced></editableAdvanced>
  <addRequired>0</addRequired>
  <splitByRationOn></splitByRationOn>
  <defaultValue></defaultValue>
  <isCalculatable>0</isCalculatable>
  <isUpdatable>0</isUpdatable>
  <visibleAdvanced></visibleAdvanced>
  <editableLevel>0</editableLevel>
  <visibleLevel>10</visibleLevel>
  <fullTypeName></fullTypeName>
  <dataType>NUMERIC</dataType>
  <dataLength>5</dataLength>
  <description source="" format="4"></description>
  <dimensionTitle></dimensionTitle>
  <definition></definition>
  <parameterName></parameterName>
  <cubeDimensionOrder>0</cubeDimensionOrder>
  <subTotalRestrictions></subTotalRestrictions>
  <subTotalExceptions></subTotalExceptions>
  <matrixHeaderValue></matrixHeaderValue>
  <promptRestricted>0</promptRestricted>
  <prompt processId="" />
  <promptOption></promptOption>
  <sortOrderForPrompt>NONE</sortOrderForPrompt>
  <filterForPrompt></filterForPrompt>
  <relatedFields></relatedFields>
  <validateAgainstPrompt>False</validateAgainstPrompt>
  <subGroupId></subGroupId>
  <indexInGroup>0</indexInGroup>
  <widthInFieldArea>2000</widthInFieldArea>
</field>

I basically want to check dataFieldType, if it's 20 or 21, check globalFormat categoryType to see if it's none, if it is, output in a file as a Field that hasn't been set properly. but I have like hundreds of fields in that xml

2 Answers

You could use Select-Xml in combination with XPath queries and Select-Object to get the element and attribute values you need. You can specify different XPaths to get to the different node levels, including element attributes, I believe.

See these examples from Microsoft docs:

$Path = "$Pshome\Types.ps1xml"
$XPath = "/Types/Type/Members/AliasProperty"
Select-Xml -Path $Path -XPath $Xpath | Select-Object -ExpandProperty Node
Name                 ReferencedMemberName
----                 --------------------
Count                Length
Name                 Key
Name                 ServiceName
RequiredServices     ServicesDependedOn
ProcessName          Name
Handles              Handlecount
VM                   VirtualSize
WS                   WorkingSetSize
Name                 ProcessName
Handles              Handlecount
VM                   VirtualMemorySize
WS                   WorkingSet
PM                   PagedMemorySize
NPM                  NonpagedSystemMemorySize
Name                 __Class
Namespace            ModuleName

For example, if you wanted to get the attributes of the globalFormat element you would do something like this:

$path = "\test.xml"
$xpath = "/field/globalFormat"
Select-Xml -Path $path -XPath $xpath | Select-Object -ExpandProperty Node

categoryType      : Number
countrySymbolCode :
dateFormat        :
timeFormat        :
imageFormat       : None
decimalPlaces     : 2
leadingZero       : 0
isCentury         : false
negativeFormat    : NegativeSymbol

If you want to access different elements and attributes at the same time, you can do something like this:

$path = "test.xml"
$xpathField = "/field"
$xpathGlobalFormat = "/field/globalFormat"
$field = Select-Xml -Path $path -XPath $xpathField | Select-Object -ExpandProperty Node
$globalFormat = Select-Xml -Path $path -XPath $xpathGlobalFormat | Select-Object -ExpandProperty Node
$field.tableName # this returns *SERVER
$globalFormat.categoryType # this returns Number

To build on Alex's helpful answer I think you are looking for an XPath query you can leverage to get the information in one shot. I was thinking something like:

(Select-Xml -Xml $Xml -XPath "/field/@* | /field/globalFormat/@categoryType").Node

I'm not exactly sure what output you are looking for, but another option would be to simply select the field nodes and just use "." referencing to get at the sub-properties to construct custom objects.

To get all of the elements and attributes under /field AND /field/globalFormat:

(Select-Xml -Xml $Xml -XPath '/field | /field/globalFormat').Node
Related