使用powershell在XML节点内设置属性

时间:2018-12-16 11:50:46

标签: xml powershell

我有一个Xml文件,其中包含如下所示的节点:

<Installation>
    <VersionData Type="Upgrade" 
    </VersionData>
    <DeploymentData>
        <DataFileGroup enable="True">
            <DataFileItem name="file2.exe.config" enable="True" installMode="Both" sourceFolder="C:\files\" distributionType="AddReplace" >
                <ItemTarget featureName="AppServer" targetPaths="$targetPath/folder3;"/>
                <ItemTarget featureName="WebServer" targetPaths="$targetPath/folder1;"/>
                <ItemTarget featureName="DBServer" targetPaths="$targetPath;"/>
            </DataFileItem>
        </DataFileGroup>
    </DeploymentData>
</Installation>

$xmlFile = "C:\work\myXML.xml"
$xml = [xml](Get-Content $xmlFile)  
$xml.Load($xmlFile)

首先,我需要获取featureName为DBServer的targetPaths的值。 然后我要更改的值:

ItemTarget featureName="DBServer" targetPaths="$targetPath;"   

ItemTarget featureName="DBServer" targetPaths="$targetPath;$concate_TargetPath"

1 个答案:

答案 0 :(得分:2)

首先,您需要通过更改来修正XML

<VersionData Type="Upgrade" 
</VersionData>

<VersionData Type="Upgrade" />

拥有有效的xml文件后,您可以执行以下操作来更新属性值:

$xmlFile = "C:\work\myXML.xml"
[xml]$xml = Get-Content $xmlFile -Raw

# find all nodes 'ItemTarget' with featureName 'DBServer'
$nodes =  $xml.SelectNodes("//ItemTarget[@featureName='DBServer']")
foreach ($node in $nodes) {
    # change the value of the 'targetPaths' attribute
    # because of the dollar signs, use single quotes here if this should be the literal value.
    # if you mean to have these values expanded from variables with these names, use double quotes
    $node.targetPaths = '$targetPath;$concate_TargetPath'
}

# save the changes to a new xml file
$xml.Save('C:\work\myXML_Updated.xml')


更新:查找要使用XPath更新的节点


从您的评论中,我了解到的内容远不止原始问题中的内容。

如果只需要更改节点targetPathsItemTarget个节点的DataFileItem属性,该节点的属性为name,其值等于a特定值, THEN targetPaths属性需要通过向其添加新路径来更改,如果,该新路径尚不存在。 (到目前为止,我是否正确?)

在这种情况下,请尝试以下操作:

# this is the name attribute to search for the DataFileItem node 
$dataFileName = "file2.exe.config"

# this is the path to add to the 'targetPaths' attribute if not already present
$newPath = "SomeNewPathToAppend"

$xmlFile =  'C:\work\myXML.xml'
[xml]$xml = Get-Content $xmlFile -Raw

# find all nodes 'ItemTarget' with featureName 'DBServer' within the 'DataFileItem' node that has attribute $dataFileName
$nodes =  $xml.SelectNodes("//DataFileItem[@name='$dataFileName']/ItemTarget[@featureName='DBServer']")
foreach ($node in $nodes) {
    # split the current value by the semicolon and remove empty elements
    $paths = $node.targetPaths.Split(";", [System.StringSplitOptions]::RemoveEmptyEntries)
    # check if the $newPath is not already in this array
    if ($paths -notcontains $newPath) {
        # change the value of the 'targetPaths' attribute by adding the $newPath to it
        $paths += $newPath
        $node.targetPaths = "{0};" -f ($paths -join ';')
    }
}

# save the changes to a new xml file
$xml.Save('C:\work\myXML_Updated.xml')


更新:查找不区分大小写的节点


由于上述代码使用区分大小写的XPath查找要更新的节点,因此它无法处理应以不区分大小写的方式比较任何namefeatureName的情况。

因此,这是一种新方法,可通过不区分大小写的比较为您提供要更新的项目:

# this is the name attribute to search for the DataFileItem node 
$dataFileName = "file2.exe.config"

# this is the path to add to the 'targetPaths' attribute if not already present
$newPath = "SomeNewPathToAppend"

$xmlFile =  'C:\work\myXML.xml'
[xml]$xml = Get-Content $xmlFile -Raw

# find all 'DataFileItem' nodes that have attribute 'name' equal to $dataFileName (case insensitive)
$nodes = $xml.GetElementsByTagName("DataFileItem") | Where-Object { $_.name -eq $dataFileName }
#  or do it like this:
#  $nodes = $xml.ChildNodes.DeploymentData.DataFileGroup.DataFileItem | Where-Object { $_.name -eq $dataFileName }

# within these 'DataFileItem' nodes, find all 'ItemTarget' elements where attribute 'featureName' equals "DBServer" (case insensitive)
$nodes.ItemTarget | Where-Object { $_.featureName -eq "DBServer" } | ForEach-Object {
    # split the current value by the semicolon and remove empty elements
    $paths = $_.targetPaths.Split(";", [System.StringSplitOptions]::RemoveEmptyEntries)
    # check if the $newPath is not already in this array
    if ($paths -notcontains $newPath) {
        # change the value of the 'targetPaths' attribute by adding the $newPath to it
        $paths += $newPath
        $_.targetPaths = "{0};" -f ($paths -join ';')
    }
}

# save the changes to a new xml file
$xml.Save('C:\work\myXML_Updated.xml')