简体   繁体   中英

PowerShell: Locate node and read its client nodes

In the XML file documented below I need to do the following:

  • Check in the structures 'General', 'Exceptions.Weekday name="Aaa"' or 'Exceptions.Date name="dd.MM.yyyy"' whether the node 'Mode name="Day"' resp. 'Mode name="Evening"' exists (without producing error output in case the node does not exist)
  • If the node exists read of each client node its content

The XML file has the following content:

<?xml version="1.0" encoding="UTF-8"?>
<P3Dcontrol>
  <General>
    <Mode name="Day">
      <P3DVersion>v4</P3DVersion>
      <FlightFile>Maule-LSZH-Schoen.fxml</FlightFile>
      <TacPackState>Inactive</TacPackState>
    </Mode>
    <Mode name="Evening">
      <P3DVersion>v4</P3DVersion>
      <FlightFile>Maule-LSZH-Schoen.fxml</FlightFile>
      <TacPackState>Active</TacPackState>
    </Mode>
  </General>
  <Exceptions>
    <Weekday name="Monday">
      <Mode name="Evening">
        <P3DVersion>v4</P3DVersion>
        <FlightFile>Maule-LSZH-Schoen.fxml</FlightFile>
        <TacPackState>Inactive</TacPackState>
      </Mode>
    </Weekday>
    <Date name="27.10.2020">
      <Mode name="Day">
        <P3DVersion>v5</P3DVersion>
        <FlightFile>Maule-LSZH-Schoen.fxml</FlightFile>
        <TacPackState>Inactive</TacPackState>
      </Mode>
    </Date>
  </Exceptions>
</P3Dcontrol>

I setup the code to read the client nodes of a node I know exists but I have not been successful; the results in the array $controlData are all empty:

# Set up working data
$mode        = GetCurrentMode # get current mode ('Day' or 'Evening')
$controlData = @{}    # initialise array for data read

# Set up new XML object and read control file content
$xmlControl = New-Object System.XML.XMLDocument
$xmlControl.Load($controlFileSpec)

# Get <General>.<Mode name=$mode> node content
$xmlControl.P3Dcontrol.General.SelectSingleNode("Mode[@Name = $mode]") | ForEach-Object {
  $controlData["P3DVersion"]   = $_.P3DVersion
  $controlData["FlightFile"]   = $_.FlightFile
  $controlData["TacPackState"] = $_.TacPackState
}

Thanks a lot for your help or hints Hannes

Once you have the XML document in $xmlControl, you should be able to work with it using standard PowerShell constructs. Perhaps something like this:

$controlData = $xmlControl.P3Dcontrol.General.Mode | Where-Object { $_.Name -eq $mode } | Select-Object P3DVersion,FlightFile,TacPackState

You can also save a line or two by using [xml] to parse XML data.


edit:

The above line will get you a custom Powershell object, where you can access the properties as $controlData.P3DVersion , $controlData.FlightFile , etc. If you need to have an array, you can keep the ForEach-Object part from your original code. Something like this:

$xmlControl.P3Dcontrol.General.Mode | Where-Object { $_.Name -eq $mode } | ForEach-Object {
     $controlData["P3DVersion"]   = $_.P3DVersion
     $controlData["FlightFile"]   = $_.FlightFile
     $controlData["TacPackState"] = $_.TacPackState
}

You can do the following to update your hash table:

$mode = 'Day'
$controlData = @{} 
$controlFileSpec = 'c:\temp\x.xml'
$xmlControl = New-Object System.XML.XMLDocument
$xmlControl.Load($controlFileSpec)

$xmlControl.P3Dcontrol.General.SelectSingleNode("Mode[@name = '$mode']") | ForEach-Object {
  $controlData["P3DVersion"]   = $_.P3DVersion
  $controlData["FlightFile"]   = $_.FlightFile
  $controlData["TacPackState"] = $_.TacPackState
}

String values in XPATH expressions need to be quoted. Since your XPATH expression contains outer double quotes, then variables will be substituted inside. You can then just use single quotes around your variables that represent values.

XPATH expressions are case-sensitive. So @Name and @name are different. Since your XML contains lowercase name attributes, you will need to match that in your expression.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM