存在多个具有不同属性的节点时选择XML

时间:2018-07-09 17:36:17

标签: xml powershell

我有如下所示的XML:

<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>

我正在使用的PowerShell代码(已更新,反映了工作代码):

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
}

我得到的错误是非终止的,并且该函数能够找到该属性。只是元素<utility>的第一次迭代不包含属性lcm,所以会引发以下错误:

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:

每当有多个<utility>节点时(如果第一个节点不包含$atttribute),我正在寻找一条错误记录。最终它将找到utility.lcm路径,但不会抛出错误。

例如,如果我要寻找utility.lcm,则第一个实用程序节点不是lcm,而是hfmcopyapp。由于未找到lcm,因此引发了错误。

如何在不引发错误的情况下选择正确的节点/属性?

也没有重新排列XML。它必须使用给定的节点属性。

1 个答案:

答案 0 :(得分:1)

我几乎总是建议通过点访问使用SelectNodes()SelectSingleNode()XPath expression,除了极少数例外。

要选择具有特定属性的节点,请使用谓词检查该属性的存在:

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

仅选择属性,请选择属性元素而不是其节点:

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

如果您需要将更多过滤条件应用于祖先节点,也可以这样做:

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