Home > Software engineering >  PowerShell XML - Get value from node depending on another nodes value
PowerShell XML - Get value from node depending on another nodes value

Time:08-24

I'm somewhat new to this so any assistance is greatly appreciated.

I need to return the <Amount> value where the sibling node <Type> contains the value "BurialFund".

The script I'm using (below the XML example) only returns the first <Amount> value from the <Asset> node so I need a way to specify which node to pull from depending on the <Type> value.

This is the line I need assistance with: $burial = Select-Xml -XPath '//AssetParent/Assets/Asset/Amount'

Other than getting the value I need, this script does what I want - reads from a folder, retrieves the necessary values, and writes to a .csv file.

Thank you in advance!

EXCERPT FROM MY XML:

<AssetParent>
    <Assets>
        <Asset>
            <Type>CheckingAccounts</Type>
            <Amount>100</Amount>
        </Asset>
        <Asset>
            <Type>SavingsAccounts</Type>
            <Amount>200</Amount>
        </Asset>
        <Asset>
            <Type>BurialFund</Type>
            <Amount>5000</Amount>
        </Asset>
    </Assets>
</AssetParent>

MY SCRIPT:

# Set the directories where this script should read from and write the results to.
$dir = 'C:\Users\username\Documents\XML\BurialAssetExclusion\'
$manifest = 'C:\Users\username\Documents\XML\BurialAssetExclusion\'   (Get-Date -Format yyyyMMdd)   '.csv'

# Process the XML files.
Get-ChildItem -Path $dir -Filter *xml | ForEach-Object {

  # Retrieve values from specified nodes.
  $interviewDate = Select-Xml -XPath '//CurrentDate' -Path $_.FullName -ErrorAction SilentlyContinue
  $burial = Select-Xml -XPath '//AssetParent/Assets/Asset/Amount' -Path $_.FullName -ErrorAction SilentlyContinue
  $dob = Select-Xml -XPath '//DOB' -Path $_.FullName -ErrorAction SilentlyContinue
  $lastName = Select-Xml -XPath '//LastName' -Path $_.FullName -ErrorAction SilentlyContinue
  $firstName = Select-Xml -XPath '//FirstName' -Path $_.FullName -ErrorAction SilentlyContinue

  # If values were retrieved succesfully.
  if ($interviewDate -and $burial -and $dob -and $lastName -and $firstName) {

    # Create a custom PSObject and set the values to corresponding properties.
    # Out-String Trim used to eliminate System.Object[] error.
    New-Object PSObject -Property @{
      InterviewDate = ($interviewDate.Node.InnerText | Out-String).Trim()
      Burial = ($burial.Node.InnerText | Out-String).Trim()
      DOB = ($dob.Node.InnerText | Out-String).Trim()
      LastName = ($lastName.Node.InnerText | Out-String).Trim()
      FirstName = ($firstName.Node.InnerText | Out-String).Trim()
    }
  }
  
  # Clear values.
  Clear-Variable interviewDate, burial, dob, lastName, firstName
  
    # Set order of columns.
    # Export data to the CSV file.
  } | Select-Object InterviewDate, Burial, DOB, LastName, FirstName | Export-Csv -Path $manifest -NoTypeInformation -append

CodePudding user response:

You can get the text node of the Amount element, where the sibling element Type contains the text "BurialFund" like this, using XPath:

$burial = $xml | Select-Xml -XPath '//AssetParent/Assets/Asset[Type="BurialFund"]/Amount/text()'
$burial.Node.Value  # Outputs 5000

Alternatively, use the convenient object access that PowerShell provides, when you load the XML into an XML document:

$xml = [xml]::new(); $xml.Load( $fullPathToXml )
$xml.AssetParent.Assets.Asset.Where{ $_.Type -eq 'BurialFund' }.Amount
  • Related