Во-первых, вам нужно будет исправить свой 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
Из вашего комментария я понимаю, что есть нечто большее, чем было яснов исходном вопросе.
Если вам нужно изменить только атрибут targetPaths
для ItemTarget
узлов, которые находятся в узле DataFileItem
, который имеет атрибут с именем name
, и его значение равноконкретное значение, THEN атрибут targetPaths
необходимо изменить, добавив новый путь к нему IF , этот новый путь еще не существует.(Правильно ли я до сих пор?)
В этом случае попробуйте следующее:
# 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, он не может обрабатывать случаи, когда любой из name
или featureName
должен сравниваться без учета регистра.
Итак, вот новый подход, который позволит вам обновлять элементы, используя сравнение без учета регистра:
# 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')