Как закрыть элемент root в XML силами PowerShell и экспортировать пачку файлов XML в единый CSV?

Есть пачка логов за несколько последних лет в виде XML:

<root>
<item date="05-08-2015" time="05:45:32.12" data1="888.8">
<data2>LOW</data2>
</item>

...

<item date="05-08-2015" time="23:45:32.04" data2="1956.2">
<data3>OK</data3>
</item>


Софтина которая генерирует эти XML почему-то не закрывает root.

Набросал такой скриптик:
[xml]$XmlDocument = Get-Content -Path LogXML-05-08-2015.log
$XmlDocument.selectNodes('//root/item') | foreach{ New-Object -TypeName psobject -Property @{date=$_.date; time=$_.time; data1=$_.data1;} } |
Export-Csv data.csv -NoTypeInformation -Encoding UTF8


При запуске скрипта в PowerShell последний ругается на отсутствие закрывающего элемента :

Непредусмотренный конец файла. Не закрыты следующие элементы: root., строка 3312, позиция 8.


Вопрос №1: как силами PowerShell добавить в обрабатываемый XML файл элемент </root> и выполнить мой скрипт?

Вопрос №2: как заставить мой скрипт обрабатывать пачки LogXML-*.log за раз, т.к. 1 файл=1сутки, а файлов много (за последние несколько лет) и результат выдавать в виде единого CSV файла?
  • Вопрос задан
  • 166 просмотров
Решения вопроса 1
@asoplevenko
программист 1С
Доброго времени суток.

1. Если мы точно знаем как поврежден xml файл – то можно его исправить. Для этого сначала загружаем содержимое файла как текст. Проверяем наличие ошибки, исправляем содержимое, и только потом преобразуем в xml.
$WorkFolder = "c:\WorkFolder"
$LogFile = $WorkFolder + "\" + "sample_0001.log"
$FileContent = (Get-Content $LogFile).Trim()
if (-not ($FileContent -match "</root>$")){$FileContent += "</root>"}
[xml]$XmlFile = $FileContent


2. Обходить файлы в каталоге/каталогах можно с помощью командлета Get-ChildItem. Он позволяет задать отбор файлов по шаблону. Собирать данные csv в одном файле позволяет опция -Append командлета Export-Csv.
$WorkFolder = "c:\WorkFolder"
$ResultFile = "$WorkFolder\result.csv"

Get-ChildItem "$WorkFolder\*.log" | ForEach-Object {

    $FileContent = (Get-Content $_).Trim()
    if (-not ($FileContent -match "</root>$")){$FileContent += "</root>"}

    [xml]$XmlFile = $FileContent

    $XmlFile.root.item | Select-Object @(
        @{l="date"; e={$_.date}}
        @{l="time"; e={$_.time}}
        @{l="data1"; e={$_.data1}}
        ) | Export-Csv -Path $ResultFile -NoTypeInformation -Append -Encoding UTF8
}


Протестировано на Powershell 5.1
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы