Разбор XML для извлечения данных с группировкой в ​​PowerShell - PullRequest
2 голосов
/ 21 апреля 2020

Пожалуйста, помогите мне извлечь данные из XML, я не могу найти логи c с небольшим знанием сценария Powershell. Мне нужно, чтобы эта логика c была реализована без установки дополнительных модулей / библиотек в powershell.

Мне нужно получить максимальный приоритет в XML, сгруппированном по KEY вместе с количеством HITS (H).

Скрипт @roadrunner, представленный ниже, работает, как и ожидалось, и это прекрасно !, но когда я запускаю файл большего размера XML (файл 2 ГБ xml), это занимает много времени для обработки, есть ли что-то, что мы можем сделать, чтобы Mutli-поток и сократить время обработки?

<ABC-FOF-PROCESS>
<H>
 <PRIORITY>-14</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
<H>
 <PRIORITY>-14</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
<H>
 <PRIORITY>-3</PRIORITY>
 <KEY>D6306210-CF424F11-8E2D3496-E6CE1CA7</KEY>
</H>
<H>
 <PRIORITY>1</PRIORITY>
 <KEY>D6306210-CF424F11-8E2D3496-E6CE1CA7</KEY>
</H>
<H>
 <PRIORITY>-3</PRIORITY>
 <KEY>4EFR02B4-ADFDAF12-3C123II2-ADAFADFD</KEY>
</H>
<H>
 <PRIORITY>-14</PRIORITY>
 <KEY>5D2702B2-ECE8F1FB-3CEC3229-5FE4C4BC</KEY>
</H>
</ABC-FOF-PROCESS>

Например, logi c ожидаемого вывода должно быть что-то вроде этого:

1-й и 2-й тег Hit имеет приоритет -14 и сгруппированы в один общий КЛЮЧ, а максимальное значение - -14.

Выходная плита для первых двух попаданий:

PRIOIRTY KEY  HITS  
-14        1     2

3-й и 4-й тег попадания имеют максимальный приоритет 1 с одним общим КЛЮЧОМ. Выходная плита:

PRIOIRTY KEY  HITS  
1        1     2

5-й тег H имеет один приоритет -3 с одним общим ключом. Выходная плита:

PRIOIRTY KEY  HITS  
-3       1     1

6-й тег H имеет один приоритет -3 с одним общим ключом. Выходная пластина:

PRIOIRTY KEY  HITS  
-14       1     1

ФИНАЛЬНЫЙ ВЫХОД (совокупный):

PRIOIRTY KEY  HITS  
1        1    2
-3       1    1
-14      2    3

Контрольный пример:

<ABC-FOF-PROCESS>
<H>
 <PRIORITY>0</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
<H>
 <PRIORITY>-2</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
<H>
 <PRIORITY>-2</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
<H>
 <PRIORITY>6</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
<H>
 <PRIORITY>3</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
<H>
 <PRIORITY>-3</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
<H>
 <PRIORITY>3</PRIORITY>
 <KEY>F637A146-3437AB82-BA659D4A-17AC7FBF</KEY>
</H>
</ABC-FOF-PROCESS>

Фактический выход:

PRIORITY KEY HITS
-------- --- ----
       6   1    1
       3   1    2
       0   1    1
      -2   1    2
      -3   1    1

Ожидаемый результат: должен быть выбран только максимальный приоритет, суммирующий все нажатия для общего ключа (F637A146-3437AB82-BA659D4A-17AC7FBF)

PRIORITY KEY HITS
-------- --- ----
       6   1    7

В моем OP 3-й и 4-й метки попадания имеют максимальный приоритет 1 (-3> 1) с одним общим КЛЮЧОМ (D6306210-CF424F11-8E2D3496-E6CE1CA7).

1 Ответ

1 голос
/ 21 апреля 2020

Вы можете сгруппировать по PRIORITY с помощью Group-Object, затем вычислить KEY (количество найденных уникальных ключей) и HITS (общее количество найденных ключей) и вставить эти свойства в а System.Management.Automation.PSCustomObject. Затем вы можете отсортировать окончательный результат по PRIORITY с помощью Sort-Object.

Для загрузки XML я использую New-Object для создания объекта System.Xml.XmlDocument, затем загружаю данные из файла с помощью System.Xml.XmlDocument.Load. Другой способ сделать это с помощью $xml = [xml](Get-Content -Path test.xml).

# Create XML object to load data into
$xml = New-Object -TypeName System.Xml.XmlDocument

# Load in XML file
$xml.Load("test.xml")

# Group XML child nodes by Priority
$groups = $xml.'ABC-FOF-PROCESS'.ChildNodes | Group-Object -Property PRIORITY

# Iterate groups and create PSCustomObject for each grouping
& {
    foreach ($group in $groups)
    {
        # Priority is group name
        # Key is just the number of unique keys found
        # Hits is the total count of the keys
        [PSCustomObject]@{
            PRIORITY = [int]$group.Name
            KEY = ($group.Group.KEY | Select-Object -Unique).Count
            HITS = $group.Count
        } 
    }
} | Sort-Object -Property PRIORITY -Descending # Sort final output by priority 

Вывод:

PRIORITY KEY HITS
-------- --- ----
       1   1    1
      -3   2    2
     -14   2    3

Чтобы вывести вышеизложенное в текстовый файл, мы можем передать вывод в Out-File:

& {
    foreach ($group in $groups)
    {
        [PSCustomObject]@{
            PRIORITY = [int]$group.Name
            KEY = ($group.Group.KEY | Select-Object -Unique).Count
            HITS = $group.Count
        }
    }
} | Sort-Object -Property PRIORITY -Descending | Out-File -FilePath output.txt
# Pipe output here
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...