todd1215
todd1215

Reputation: 413

Selecting XML when there are multiple nodes with different attributes

I have XML that looks like this:

<config>
    <backup>
        <environment>
            <server name="exampleserver2" type="FM">
                <utility hfmcopyapp="C:\Oracle\Middleware\EPMSystem11R1\products\FinancialManagement\Utilities\HfmCopyAppCmd_x64.exe"/>
                <utility lcm="C:\Oracle\Middleware\user_projects\FM1\bin\Utility.bat"/>
            </server>
        </environment>
    </backup>
</config>

The PowerShell code I am using is (updated, reflects working code):

function Get-ServerAttrByXmlTag
{
    [OutputType([string])]
    param
    (
        [Parameter(Mandatory = $true)]
        [string]$server,
        [string]$type,
        [string]$feature,
        [string]$xmltag,
        [string]$attribute

    )

    if ($type)
    {
        $Value = $xmlDoc.SelectSingleNode("//server[@name='$server' and @type='$type']/$xmltag/@$attribute").'#text'
    }
    else
    {
        $Value = $xmlDoc.SelectSingleNode("//server[@name='$server']/$xmltag/@$attribute").'#text'
    }
    $Value
}

The error I get is non-terminating and the function is able to find the attribute. It's just that the first iteration of element <utility> doesn't contain the attribute lcm, so it throws this error:

ERROR: Select-Object : Property "lcm" cannot be found. Common.ps1 (114, 5):
ERROR: At Line: 114 char: 5
ERROR: +              Select-Object -ExpandProperty $attribute
ERROR: +              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ERROR:     + CategoryInfo          : InvalidArgument: (utility:PSObject) [Select-Object], PSArgumentException
ERROR:     + FullyQualifiedErrorId : ExpandPropertyNotFound,Microsoft.PowerShell.Commands.SelectObjectCommand
ERROR:

Whenever there are multiple <utility> nodes if the first one doesn't contain the $atttribute I am looking for an error record is throw. It will eventually find the utility.lcm path but not without an error being throw.

For example if I am looking for utility.lcm The first utility node isn't lcm, it's hfmcopyapp. So an error is thrown because lcm wasn't found.

How can I select the correct node/attribute without throwing an error?

There's no rearranging the XML either. It has to work with the nodes attributes given.

Upvotes: 0

Views: 2097

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200193

I would practically always recommend using SelectNodes() or SelectSingleNode() with an XPath expression over dot-access, with very few exceptions.

For selecting a node with a particular attribute use a predicate that checks for the presence of that attribute:

$xml.SelectNodes('//utility[@lcm]')

For selecting just the attribute select the attribute element instead of its node:

$xml.SelectNodes('//utility/@lcm')

If you need further filter criteria applied to ancestor nodes you can do that as well:

$xml.SelectNodes("//server[@name='$server' and @type='$type']/utility/@lcm")

Upvotes: 1

Related Questions