A
A
Alexander Lozovoy2018-09-21 15:25:52
PowerShell
Alexander Lozovoy, 2018-09-21 15:25:52

How to close the root element in XML with PowerShell and export a bunch of XML files into a single CSV?

There is a bunch of logs for the last few years in the form of 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>

The software that generates these XML for some reason does not close root.
I wrote this script:
[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

When running a script in PowerShell, the latter swears at the absence of a closing element:
Unexpected end of file. The following elements are not closed: root., line 3312, position 8.

Question number 1: how can I add an element to the processed XML file using PowerShell </root>and execute my script?
Question number 2: how to make my script process batches of LogXML-*.log at a time, because 1 file = 1 day, but there are a lot of files (over the past few years) and the result is output as a single CSV file?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Andrey Soplevenko, 2018-09-23
@aerounit

Good day.
1. If we know exactly how the xml file is damaged, then we can fix it. To do this, we first load the contents of the file as text. We check for an error, fix the content, and only then convert it to 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. You can traverse the files in the directory/directories using the Get-ChildItem cmdlet. It allows you to set the selection of files by template. The -Append option of the Export-Csv cmdlet allows you to collect csv data in a single file.
$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
}

Tested on Powershell 5.1

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question