简体   繁体   English

如何使用Powershell将重复的xml节点转换为逗号分隔的字符串

[英]How do I convert repeated xml nodes into a comma delimited string using powershell

I have some 13000 log files that are formatted in XML format and I need to convert all of them into a spreadsheet\\csv file. 我有一些13000个以XML格式格式化的日志文件,我需要将它们全部转换为电子表格\\ csv文件。

As you will see I'm not programmer but I've tried. 如您所见,我不是程序员,但我已经尝试过。
I have written a powershell script to get the first nodes out and create a comma delimited string but I am stuck with getting the last node which can contain anything from no entries to dozens. 我已经编写了一个powershell脚本来取出第一个节点并创建一个逗号分隔的字符串,但是我坚持使用最后一个节点,该节点可以包含从无条目到数十个条目的任何内容。

example of the xml file: xml文件的示例:

<?xml version="1.0" encoding="utf-8"?>
<MigrationUserStatus>
  <User>username@domain.com</User>
  <StoreList>
    <EmailMigrationStatus>
      <MigrationStatus value="Success" />
      <FolderList>
        <TotalCount value="6" />
        <SuccessCount value="3" />
        <FailCount value="3" />
        <FailedMessages>
          <ErrorMessage>GDSTATUS_BAD_REQUEST:Permanent failure: BadAttachment</ErrorMessage>
          <SentTime>1601-01-01T00:00:00.000Z</SentTime>
          <ReceiveTime>1601-01-01T00:00:00.000Z</ReceiveTime>
        </FailedMessages>
        <FailedMessages>
          <ErrorMessage>GDSTATUS_BAD_REQUEST:Permanent failure: BadAttachment</ErrorMessage>
          <SentTime>1601-01-01T00:00:00.000Z</SentTime>
          <ReceiveTime>1601-01-01T00:00:00.000Z</ReceiveTime>
        </FailedMessages>
        <FailedMessages>
          <MessageSubject>Hey</MessageSubject>
          <ErrorMessage>GDSTATUS_BAD_REQUEST:Permanent failure: BadAttachment</ErrorMessage>
          <SentTime>2013-01-07T02:51:17.000Z</SentTime>
          <ReceiveTime>2013-01-07T02:51:17.000Z</ReceiveTime>
          <MessageSize value="2881" />
        </FailedMessages>
        <StartTime>2013-01-07T01:52:46.000Z</StartTime>
        <EndTime>2013-01-07T04:41:59.000Z</EndTime>
      </FolderList>
      <StartTime>2013-01-07T01:52:43.000Z</StartTime>
      <EndTime>2013-01-07T04:41:59.000Z</EndTime>
    </EmailMigrationStatus>
    <StartTime>2013-01-07T01:52:43.000Z</StartTime>
    <EndTime>2013-01-07T04:41:59.000Z</EndTime>
  </StoreList>
</MigrationUserStatus>

With this code I can easily get the the first parts of the csv line created: 使用此代码,我可以轻松地获得创建的csv行的第一部分:

$folder = "C:\temp"
$outfile = = [IO.File]::OpenWrite("alluserslogs.csv")
$csv = "User,Total Emails, Successful emails,Failed emails,Failures`r`n"

dir Status-*.log | foreach ( $_) {
[xml]$Status = Get-Content $_
$csvpt1 +=$Status.MigrationUserStatus.User + "," + $Status.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.TotalCount.value + "," + $Status.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.SuccessCount.value + "," + $Status.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.FailCount.value

The next bit is where I'm coming unstuck. 下一点是我要解脱的地方。 I want to read each FailedMessages node and build it to another comma delimited string 我想阅读每个FailedMessages节点并将其构建为另一个逗号分隔的字符串

foreach ($FMessage in $Status.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.FailedMessages) {
$csvpt2 +=$FMessage + ","
}

Desired output: 所需的输出:

GDSTATUS_BAD_REQUEST:Permanent failu... 1601-01-01T00:00:00.000Z                1601-01-01T00:00:00.000Z,GDSTATUS_BAD_REQUEST:Permanent failu... 1601-01-01T00:00:00.000Z                1601-01-01T00:00:00.000Z,.......

I get either blank in $FMessage or Method invocation failed because of the + "," at the end so I need this fixed. 我在$ FMessage中留空,或者由于最后的+“,”导致方法调用失败,因此需要修复此问题。

then I'll concatenate into one final string and write to file 然后我将其连接成一个最后的字符串并写入文件

$csv +=$csvpt1 + "," + $csvpt2
$outfile.WriteLine($csv)
}
$outfile.Close()

In an added wish list it would also be great to be able to create the csv file columns header Failures for n number of columns as depicted by the largest number of FailedMessages nodes. 在添加的愿望列表中,能够为n个列创建csv文件列标头失败也是一件很棒的事情,如FailedMessages节点的最大数量所描绘的那样。

Your assistance is greatly appreciated. 非常感谢您的协助。

Powershell has native support for XML, maybe this will help get you started? Powershell具有对XML的本地支持,也许这可以帮助您入门?

It also has a native CSV Exporter with Export-Csv :) 它还具有带有Export-Csv的本地CSV导出器:)

[xml]$XMLfile = gc C:\Temp\migration.xml

$MasterArray = @()
$MasterArray = "" | Select User, Result, TotalEmails, SuccessfulEmails, FailedEmails, Failures

$MasterArray.User = $XMLfile.MigrationUserStatus.user
$MasterArray.Result = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.MigrationStatus.value
$MasterArray.TotalEmails = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.TotalCount.value
$MasterArray.SuccessfulEmails = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.SuccessCount.value
$MasterArray.FailedEmails = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.FailCount.value

$Failures = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.FailedMessages
$ConcatFailures = @()
foreach ($Failure in $Failures)
{
    $ConcatFailures += $Failure.ErrorMessage + "," + $Failure.SentTime + "," + $Failure.ReceivedTime
}

$MasterArray.Failures = $ConcatFailures -Join "|"
$MasterArray
$MasterArray | Export-Csv -NoType "C:\Temp\export.csv"

For the other fields, you can check if they exist and add them if they do pretty easily, this should work: 对于其他字段,您可以检查它们是否存在,如果很容易添加,则可以添加它们,这应该可以:

foreach ($Failure in $Failures)
{
    if ($Failure.ErrorMessage) { $ConcatFailures += $Failure.ErrorMessage }
    if ($Failure.SentTime) { $ConcatFailures += $Failure.ErrorMessage }
    if ($Failure.ReceivedTime) { $ConcatFailures += $Failure.ReceivedTime }
    if ($Failure.MessageSubject) { $ConcatFailures += $Failure.MessageSubject }
    if ($Failure.MessageSize) { $ConcatFailures += $Failure.MessageSize }
}

To handle the xml files you want to add an outer loop to go through all of the xml files, and then append the data into an array that you build up as you go. 要处理xml文件,您需要添加一个外部循环以遍历所有xml文件,然后将数据附加到随行建立的数组中。 This should do what you want, with some adjustments to the paths used: 这应该做您想要的,并对使用的路径进行一些调整:

$XMLFiles = gci "C:\Temp\" -Filter "*.xml"
$MasterArray = @()

foreach ($XMLFile in $XMLFiles)
{
    [xml]$XMLfile = gc $XMLFile.FullName

    $TempArray = @()
    $TempArray = "" | Select User, Result, TotalEmails, SuccessfulEmails, FailedEmails, Failures

    $TempArray.User = $XMLfile.MigrationUserStatus.user
    $TempArray.Result = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.MigrationStatus.value
    $TempArray.TotalEmails = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.TotalCount.value
    $TempArray.SuccessfulEmails = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.SuccessCount.value
    $TempArray.FailedEmails = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.FailCount.value

    $Failures = $XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.FailedMessages
    $ConcatFailures = @()

    foreach ($Failure in $Failures)
    {
        if ($Failure.ErrorMessage) { $ConcatFailures += $Failure.ErrorMessage }
        if ($Failure.SentTime) { $ConcatFailures += $Failure.ErrorMessage }
        if ($Failure.ReceivedTime) { $ConcatFailures += $Failure.ReceivedTime }
        if ($Failure.MessageSubject) { $ConcatFailures += $Failure.MessageSubject }
        if ($Failure.MessageSize) { $ConcatFailures += $Failure.MessageSize }
    }
    $TempArray.Failures = $ConcatFailures -Join "|"

    $MasterArray += $TempArray
}

$MasterArray
$MasterArray | Export-Csv -NoType "C:\Temp\export.csv"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM