Извлечь элемент из файла XML по позиции в иерархии, а не по имени - PullRequest
1 голос
/ 15 марта 2019

У меня есть XML-файл, подобный этому:

<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

У меня есть скрипт Powershell, подобный этому:

$xmlData = New-Object -TypeName System.Xml.XmlDocument
$xmlData.Load('c:\test\data.xml')
$xmlData.note.body # I want to remove "note.body" to change to use function

Можно ли получить значение того, что в данный момент является элементом note.body, без необходимости использовать элемент names , т. Е. Можно ли извлечь значения по позиции целевого элемента в иерархии документов

Идея состоит в том, чтобы иметь скрипт, который продолжает работать даже после изменения имен элементов во входном XML-коде (но не в структуре документа ).

1 Ответ

2 голосов
/ 15 марта 2019

Если вы хотите найти интересующий элемент позиционно , используйте общие свойства XML DOM:

In PowerShell Core :

# Extract the text from the *last child* of the *document element*.
# This is the positional equivalent of your $xmlData.note.body call.
# Of course, you can use specific indices such as [2] as well.
$xmlData.DocumentElement.ChildNodes[-1].InnerText

Для вашего образца документа вывод будет Don't forget me this weekend!, как и ожидалось.


In Windows PowerShell (все обходные пути)работать и в PowerShell Core):

A ошибка не позволяет использовать [-1] для ссылки на элемент last коллекции вэтот случай.

Обходной путь 1 :

$childNodes = $xmlData.DocumentElement.ChildNodes  
$childNodes[$childNodes.Count-1].InnerText

Обходной путь 2 :

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

Используйте перечисление членов , чтобы извлечь .InnerText значения из всех дочерних узлов вверхfront - который возвращает обычный массив PowerShell - и применяет [-1] к , что :

$xmlData.DocumentElement.ChildNodes.InnerText[-1]

Обходной путь 3 , предложенный Tomalak :

$xmlData.DocumentElement.ChildNodes |
  Select-Object -Last 1 -ExpandProperty InnerText

Select-Object -Last 1 удается извлечь последний дочерний элемент, а -ExpandProperty InnerText затем возвращает значение свойства .InnerText.

Обратите внимание, что это решение обычно работает хуже всего из обходных путей.из-за использования командлета в конвейере, опять же, это, вероятно, не будет иметь значения на практике, если вы не вызовете этот код в цикле с большим количеством итераций.

...