如何使用powershell将重复的xml节点转换为逗号分隔的字符串
我有大约13000个以XML格式格式化的日志文件,我需要将它们全部转换为电子表格\csv文件 正如您将看到的,我不是程序员,但我已经尝试过了。如何使用powershell将重复的xml节点转换为逗号分隔的字符串,xml,powershell,nodes,Xml,Powershell,Nodes,我有大约13000个以XML格式格式化的日志文件,我需要将它们全部转换为电子表格\csv文件 正如您将看到的,我不是程序员,但我已经尝试过了。 我已经编写了一个powershell脚本来获取第一个节点并创建一个逗号分隔的字符串,但是我一直在获取最后一个节点,它可以包含从没有条目到几十个条目的任何内容 xml文件的示例: <?xml version="1.0" encoding="utf-8"?> <MigrationUserStatus> <User>us
我已经编写了一个powershell脚本来获取第一个节点并创建一个逗号分隔的字符串,但是我一直在获取最后一个节点,它可以包含从没有条目到几十个条目的任何内容 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>
下一步就是我要摆脱困境的地方。我想读取每个FailedMessages节点,并将其构建为另一个逗号分隔的字符串
foreach ($FMessage in $Status.MigrationUserStatus.StoreList.EmailMigrationStatus.FolderList.FailedMessages) {
$csvpt2 +=$FMessage + ","
}
期望输出:
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,.......
我要么在$FMessage中得到空白,要么方法调用失败,因为结尾有+“,”,所以我需要修复这个问题
然后我将连接成最后一个字符串并写入文件
$csv +=$csvpt1 + "," + $csvpt2
$outfile.WriteLine($csv)
}
$outfile.Close()
在添加的愿望列表中,能够为n个列创建csv文件列标题故障也将非常好,如FailedMessages节点的最大数量所示
非常感谢您的帮助。Powershell具有对XML的本机支持,也许这将帮助您开始 它还有一个本机CSV导出器,带有导出CSV:) 对于其他字段,您可以检查它们是否存在,如果它们很容易添加,则可以添加它们,这应能起作用:
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 }
}
要处理xml文件,您需要添加一个外部循环来遍历所有xml文件,然后将数据附加到一个在运行过程中构建的数组中。这应该满足您的需要,并对使用的路径进行一些调整:
$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"
Powershell具有对XML的本机支持,这可能有助于您入门 它还有一个本机CSV导出器,带有导出CSV:) 对于其他字段,您可以检查它们是否存在,如果它们很容易添加,则可以添加它们,这应能起作用:
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 }
}
要处理xml文件,您需要添加一个外部循环来遍历所有xml文件,然后将数据附加到一个在运行过程中构建的数组中。这应该满足您的需要,并对使用的路径进行一些调整:
$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"
感谢HungryHippos,我看到您的解决方案的唯一问题是,它假设只有ErrorMessage、SentTime和ReceivedTime,而在示例XML中,第三条failedmessage中有MessageSubject和MessageSize。我想包括主题,如果它存在,但它并不总是存在。再次感谢您的回复,我将看看是否可以稍微修改它,以包含MessageSubject(如果存在的话),并对您可能如何处理它稍感遗憾。也可能是(虽然我没有测试过)如果你在中添加了其他字段,那么$Null可能根本不会处理它们,除非它们存在。再次感谢HungryHippos,我尝试了另一种方式,但更喜欢并将使用你的解决方案。指定的最后一件事是,我需要对大约13000个日志文件运行它,并将它们合并到一个csv文件中。我尝试过,但它总是覆盖以前创建的csv文件。我更新了原始文件,以展示如何添加外部循环以使其正常工作:)再次感谢@HungryHippos,我稍微修改了您的代码以解决一些意外输出,因为唯一的Concatfailures是最后一个文件,这通过添加foreach解决($XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.Folderlist中的$Folderlist)我添加了一个检查,因为并非所有文件都有错误消息,最后我包括了所有计数的总和(成功、失败和总数)对于所有的文件。再次感谢,您为我省去了很多麻烦。感谢HungryHippos,我能看到您的解决方案的唯一问题是,它假设只有ErrorMessage、SentTime和ReceivedTime,而在提供的示例XML中,第三条failedmessage中有MessageSubject和MessageSize。我想包括Subject如果它存在,但它并不总是存在。再次感谢您的回复,我会看看是否可以稍微修改它,以包含MessageSubject(如果存在)。请稍微说明您如何处理它。它也可能存在(尽管我尚未测试)如果您在中添加了其他字段,$Null可能根本无法处理它们,除非它们存在。再次感谢HungryHippos,我尝试了另一种方式,但更喜欢并将使用您的解决方案。最后指定的是,我需要对大约13000个日志文件运行此操作,并将它们合并到一个csv文件中。我尝试了但它总是覆盖以前创建的csv文件。我更新了原始文件,以展示如何添加外部循环以使其工作:)再次感谢@HungryHippos,我稍微修改了您的代码以解决一些意外输出,因为唯一的Concatfailures是最后一个文件,这是通过添加foreach解决的($XMLfile.MigrationUserStatus.StoreList.EmailMigrationStatus.Folderlist中的$Folderlist)我添加了一个检查,因为不是所有文件都有错误消息,最后我包括了所有文件的所有计数总和(成功、失败和总数)。再次感谢,您为我省去了很多麻烦。