KBEC-00071 - Navigating to properties in a nested property sheet

Article ID:360033194571
2 minute readKnowledge base

Description

The ElectricCommander ectool Reference and User Guide has an example of how to find a property. Navigating into a nested property sheet requires a different technique.

Solution

  1. To find all nested property sheets in one call (from any one object), use the getProperties call with the "recurse" option. This action returns an XPath object with the full hierarchy. (This technique is not recommended if the size of the entire returned XML text is more than about 500 KB.

  2. Use XPath to navigate through the returned result. Below is an example that reads an entire hierarchy and reproduces it on the current job. You can modify the hierarchy to do whatever you need, but the walking of the hierarchy should be the same either way. The first parameter is the XPath object containing the property sheet that was returned from getProperties.

    Example Function Code

     sub CopyPropertySheetToJob(@@@)
     {
         my $xPath = shift;
         my $propertySheetNode = shift;
         my $destPropertySheet = shift;
    
         # Find the properties in the sheet
         #print $xPath->findnodes_as_string(".", $propertySheetNode) . "\n";
         my $propertyNodeset = $xPath->find('property', $propertySheetNode);
    
         # If there are no subnodes, just create the Property Sheet
         if ($propertyNodeset->size() == 0) {
             $ec->createProperty("/myJob/$destPropertySheet",
                                 {
                                     propertyType       =>  "sheet",
                                     jobStepId => $ENV{COMMANDER_JOBSTEPID}
                                 });
    
         }
    
         # Process each property in the sheet
         foreach my $propertyNode ($propertyNodeset->get_nodelist)
         {
             my $propertyName = $xPath->findvalue('propertyName', $propertyNode);
             my @subSheetNodes = $xPath->findnodes('./propertySheet', $propertyNode);
             if (@subSheetNodes) {
                 # Recursively copy the subsheet
                 my $subSheet = $destPropertySheet . "/$propertyName";
                 CopyPropertySheetToJob($xPath, $subSheetNodes[0], $subSheet);
             }
             else {
                 # Create the property
                 my $propertyValue = $xPath->findvalue('value', $propertyNode);
                 # print "Copying Property $propertyName to $destPropertySheet\n";
                 $ec->setProperty("/myJob/$destPropertySheet/$propertyName",
                                   $propertyValue,
                                   {jobStepId => $ENV{COMMANDER_JOBSTEPID}});
             }
         }
     }

    ## Example calling code

    This top-level function iterates over property sheets calling the recursive function, passing in the top-level node of the xPath that is returned.
    Note that expansion is disabled, because if there is a property reference INSIDE one of the properties, the copy function should just copy the property reference text (e.g, "$[/myStep/stepName]"). It should not try to expand it.

     use strict;
     use ElectricCommander;
     $| = 1;
     my $ec = new ElectricCommander;
    
    
     # Get the name of a project from a parameter
     my $projectName = "$[/myCall/sourceProject]";
     copyProjectPropertiesToJob($projectName);
    
     sub  copyProjectPropertiesToJob(@)
     {
    
        # Disable property expansion - we just want to copy the text of a property reference
        my $projectForProperties = shift;
        my $xPath = $ec->getProperties(
                             {projectName => $projectForProperties,
                              recurse     => "1",
                              expand      => "0"});
    
        if (defined $xPath) {
           # Find the top-level node of the property sheet (there is just one)
           #   then use the recursive copy
           my @propertySheetNodes = $xPath->findnodes('/responses/response/propertySheet');
           CopyPropertySheetToJob($xPath, $propertySheetNodes[0], "");
        }
     }

    ## newer techniques

    In Commander release 3.6 and after the following ectool command will perform the same as the above copy:

     ectool clone --path '$[/myCall/sourceProject]' --cloneName '/myJob'