Найти главный элемент на основе значения дочернего элемента, затем изменить значение другого дочернего элемента - PullRequest
1 голос
/ 08 марта 2019

У меня есть XML-файл со следующей структурой:

<PARENT>
    <LIBRARY>
        <BOOKS>
            <BOOK>
                <BOOK_DATA>
                    <BOOK_TITLE>HOBBIT</BOOK_TITLE>
                </BOOK_DATA>
                <STATUS>NotRead</STATUS>
            </BOOK>
            <BOOK>
                <BOOK_DATA>
                    <BOOK_TITLE>LOTR_FOTR</BOOK_TITLE>
                </BOOK_DATA>
                <STATUS>NotRead</STATUS>
            </BOOK>
            <BOOK>
                <BOOK_DATA>
                    <BOOK_TITLE>LOTR_TT</BOOK_TITLE>
                </BOOK_DATA>
                <STATUS>NotRead</STATUS>
            </BOOK>
            <BOOK>
                <BOOK_DATA>
                    <BOOK_TITLE>LOTR_ROTK</BOOK_TITLE>
                </BOOK_DATA>
                <STATUS>NotRead</STATUS>
            </BOOK>
        </BOOKS>
    </LIBRARY>
</PARENT>

При использовании сценария powershell мне нужно найти элемент BOOK, содержащий $ BookTitle, а затем изменить значение элемента STATUS на $ NewStatus

Пример:

$ BookTitle = LOTR_TT

$ NewStatus = Читать

Находит:

        <BOOK>
            <BOOK_DATA>
                <BOOK_TITLE>LOTR_TT</BOOK_TITLE>
            </BOOK_DATA>
            <STATUS>NotRead</STATUS>
        </BOOK>

И изменяет его на:

        <BOOK>
            <BOOK_DATA>
                <BOOK_TITLE>LOTR_TT</BOOK_TITLE>
            </BOOK_DATA>
            <STATUS>Read</STATUS>
        </BOOK>

У меня есть следующее в StatusChanger.ps1, но оно не дает ожидаемых результатов:

param ($BookTitle = LOTR_TT)
param ($NewStatus = Read)
param ($FilePath = C:\file.xml)

#Open the file
[xml]$xml = Get-Content -Path $FilePath

$xml.parent.library.books.book | where { $_.book_data.book_title -like "$BookTitle" } | ForEach {
$_.STATUS = '$NewStatus'
}

#Save the updated file
$xml.Save($FilePath)

Ответы [ 3 ]

0 голосов
/ 08 марта 2019

Я предлагаю использовать XPath для этой проблемы:

[xml]$xml = ' ... '

$bookTitle = 'LOTR_TT'
$newStatus = 'Read'
$node = $xml.SelectSingleNode("//BOOK[BOOK_DATA/BOOK_TITLE='$bookTitle']/STATUS")
$node.'#text' = $newStatus

Важной частью здесь является фильтр:

//BOOK[BOOK_DATA/BOOK_TITLE='$bookTitle']/STATUS

Это выберет узел STATUS из книги, соответствующий фильтру BOOK_TITLE='$bookTitle', и PowerShell выставит InnerText в качестве свойства #text.


Используется в вашем примере скрипта:

param(
    [string]
    $BookTitle = 'LOTR_TT',

    [string]
    $NewStatus = 'Read',

    [string]
    $FilePath = 'C:\file.xml'
)

[xml]$xml = Get-Content -Path $FilePath

$node = $xml.SelectSingleNode("//BOOK[BOOK_DATA/BOOK_TITLE='$BookTitle']/STATUS")
$node.'#text' = $NewStatus

$xml.Save($FilePath)

В качестве альтернативы, поэтому, если вы хотите найти ВСЕ узлы, содержащие строку, которую нужно изменить для чтения, вы можете сделать следующее:

$xml.SelectNodes("//BOOK[BOOK_DATA/BOOK_TITLE[contains(., '$BookTitle')]]/STATUS") |
    ForEach-Object { $_.'#text' = $NewStatus }
0 голосов
/ 08 марта 2019

Насколько я вижу, в вашем коде есть две ошибки:

  1. Вы должны заключить в кавычки значения для $BookTitle и $NewStatus, чтобы они стали
    $BookTitle = 'LOTR_TT' и $NewStatus = 'Read'
  2. Вы заключаете это в одинарные кавычки: $_.STATUS = '$NewStatus' и тем самым устанавливаете для STATUS значение literal , равное "$ NewStatus". Удалите эти кавычки, чтобы вставить значение переменной:

    $_.STATUS = $NewStatus

После этого, если у меня нормально работает.

0 голосов
/ 08 марта 2019

Я бы предложил найти элемент по тэгу. Затем вам нужно подняться выше по иерархии, чтобы получить доступ к соответствующему статусу Книги.

Тогда легко установить статус.

$foundedElement = $test.GetElementsByTagName("BOOK_TITLE") |Where-Object {$_."#text" -eq $BookTitle}

$foundedElement.ParentNode.ParentNode.STATUS = $NewStatus

$test.Save($fileName)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...