Извлечение ранних значений атрибутов без полного Get-Content - PullRequest
1 голос
/ 04 ноября 2019

В PowerShell я знаю, что могу сделать что-то вроде этого:

[xml]$myxml = Get-Contents .\oneofmyxmlfiles.xml
$myxml.Wrapper.Data.HeaderStuff.SomeHeaderAttribute

и получить желаемый результат (WhatIWantToExtract) из чего-то вроде

<Wrapper>
    <Data>
        <HeaderStuff SomeHeaderAttribute="WhatIWantToExtract" />
...a bunch of other stuff...
    </Data>
...a bunch of more other stuff...
</Wrapper>

Мне нужно сделатьэто для многих файлов, которые могут быть довольно большими . Но элемент HeaderStuff уникален и всегда очень в верхней части файла.

Есть ли способ извлечь "непосредственно" из верхней части файла, без загрузки всего содержимого с помощью Get-Content?

Ответы [ 2 ]

1 голос
/ 04 ноября 2019

Вы можете использовать .NET XmlReader для чтения в файл XML и прекращения дальнейшей его обработки, как только у вас появится нужная информация.

Преимущество: это очень быстро ииспользует рядом без памяти. Недостаток: вы должны использовать, например, флаги, чтобы поддерживать контекст того, что вы читаете, потому что читатель работает как перемещение курсора по файлу. Он только сохраняет свою позицию и на что он сейчас смотрит;Вы должны вести всю необходимую бухгалтерию.

Следующее возвращает значение атрибута SomeHeaderAttribute первого элемента <HeaderStuff>, с которым он сталкивается, и прекращает обработку после этого. Приспосабливайтесь к вашему конкретному XML-макету и нуждам.

using namespace System.IO
using namespace System.Xml

function Get-HeaderStuff {
    param([string]$xmlFilePath)

    try {
        $stream = New-Object FileStream -ArgumentList ($xmlFilePath, [FileMode]::Open)

        $settings = New-Object XmlReaderSettings
        $settings.Async = $false

        $reader = [XmlReader]::Create($stream, $settings)
        while ($reader.Read()) {
            if (
                $reader.NodeType -eq [XmlNodeType]::Element -and 
                $reader.Name -eq "HeaderStuff"
            ) {
                return $reader.GetAttribute("SomeHeaderAttribute")
            }
        }
    } finally {
        # clean up
        if ($reader) { $reader.Dispose() }
        if ($stream) { $stream.Dispose() }
    }
}

Вы бы назвали его путем к вашему XML-файлу:

$result = Get-HeaderStuff ".\oneofmyxmlfiles.xml"
Write-Host $result
0 голосов
/ 13 ноября 2019

Я буду использовать предложение TheIncorrigible1, «использовать параметр TotalCount Get-Content»:

$fivelines = Get-Content .\oneofmyxmlfiles.xml -TotalCount 5

В результате получается System.Array с пятью элементами. Мои XML-файлы имеют очень предсказуемую структуру, поэтому я могу легко выделить нужную мне строку (элемент массива), а затем использовать простые методы сопоставления строк, чтобы получить значение атрибута, которое мне нужно.

Благодаря Томалаку,Ваше решение кажется более элегантным и надежным, но требует больше работы, чем я готов в данный момент.

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