Reputation: 413
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
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