использование powershell для установки атрибута внутри узла XML - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть 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)

Сначала мне нужно получить значение targetPaths, где featureName равно DBServer.Затем я хочу изменить значение:

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

на

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

1 Ответ

0 голосов
/ 16 декабря 2018

Во-первых, вам нужно будет исправить свой 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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...