解析类似 XML 的日志文件 [英] Parsing XML-Like log file
问题描述
我有一个记录事件的日志文件,如下所示.我想将每个事件转换为 PSCustomobject.它有点像 XML,但将 xml 转换为文件的 Get-Content 给了我一个错误:
I have a log file which records events as follows. I would like convert each event into a PSCustomobject. It kinda looks like XML but casting xml to the Get-Content for the file gives me an error:
无法将值System.Object[]"转换为类型System.Xml.XmlDocument".错误:此文档已有一个 'DocumentElement' 节点."
Cannot convert value "System.Object[]" to type "System.Xml.XmlDocument". Error: "This document already has a 'DocumentElement' node."
<event date='Jan 06 01:46:16' severity='4' hostName='ABC' source='CSMFAgentPolicyManager' module='smfagent.dll' process='AeXNSAgent.exe' pid='1580' thread='1940' tickCount='306700046' >
<![CDATA[Setting wakeup time to 3600000 ms (Invalid DateTime) for policy: DefaultWakeup]]>
</event>
这是我到目前为止的一段代码
Here is the piece of code I have so far
<#
.EXAMPLE
source : MaintenanceWindowMgr
process : AeXNSAgent.exe
thread : 8500
hostName : ABC
severity : 4
tickCount : 717008140
date : Jan 10 19:45:00
module : PatchMgmtAgents.dll
pid : 11984
CData : isAbidingByMaintenanceWindows() - yes
#>
$logpath = Join-Path $env:ProgramData 'Symantec\Symantec Agent\logs\Agent.log'
$hash=[ordered]@{};
$log = get-content $logpath | % {
## handle Event start
## sample: <event date='Jan 10 18:45:00' severity='4' hostName='ABC' source='MaintenanceWindowMgr' module='PatchMgmtAgents.dll' process='AeXNSAgent.exe' pid='11984' thread='8500' tickCount='713408140' >
if ($_ -match '^<event') {
if ($hash) {
## Convert the hastable to PSCustomObject before clearing it
New-Object PSObject -Property $hash
$hash.Clear()
}
$line = $_ -replace '<event ' -replace ' >' -split "'\s" -replace "'"
$line | % {
$name,$value=$_ -split '='
$hash.$name=$value
}
}
## handle CData
## Sample: <![CDATA[Schedule Software Update Application Task ({A1939DC8-DA4A-4E46-9629-0500C2383ECA}) triggered at 2014-01-10 18:50:00 -5:00]]>
if ($_ -match '<!') {
$hash.'CData' = ($_ -replace '<!\[CDATA\[' -replace '\]\]>$').ToString().Trim()
}
}
$log
不幸的是,对象不是我想要的形式.
Unfortunately, the object is not in the form I would want it.
$log|gm
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
当我尝试从输出中收集所有对象时,我丢失了将哈希转换为 PSCustomObject 时生成的 NoteProperties
When I try to collect all the objects from the output, I am losing the NoteProperties that are generated when I convert the hash to PSCustomObject
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
CData NoteProperty System.String CData=isAbidingByMaintenanceWindows() - yes
date NoteProperty System.String date=Jan 10 18:45:00
hostName NoteProperty System.String hostName=ABC
module NoteProperty System.String module=PatchMgmtAgents.dll
pid NoteProperty System.String pid=11984
process NoteProperty System.String process=AeXNSAgent.exe
severity NoteProperty System.String severity=4
source NoteProperty System.String source=MaintenanceWindowMgr
thread NoteProperty System.String thread=8500
tickCount NoteProperty System.String tickCount=713408140
我在这里错过了什么?
推荐答案
XML 文件必须具有单个根(或 documentElement
)节点.由于您的日志文件似乎包含多个 <event>
标记而没有公共根元素,您可以像这样添加缺少的 documentElement
:
XML files must have a single root (or documentElement
) node. Since your log file seems to contain multiple <event>
tags without a common root element you can add the missing documentElement
like this:
$logpath = Join-Path $env:ProgramData 'Symantec\Symantec Agent\logs\Agent.log'
[xml]$log = "<logroot>$(Get-Content $logpath)</logroot>"
之后,您可以使用通常的方法处理您的日志,例如:
After that you can process your log with the usual methods, e.g.:
$fmt = 'MMM dd HH:mm:ss'
$log.SelectNodes('//event') |
select @{n='date';e={[DateTime]::ParseExact($_.date, $fmt, $null)}},
severity, hostname, @{n='message';e={$_.'#cdata-section'}}
如果您更喜欢自定义对象,您可以像这样轻松创建它们:
If you prefer custom objects you can easily create them like this:
$fmt = 'MMM dd HH:mm:ss'
$log.SelectNodes('//event') | % {
New-Object -Type PSObject -Property @{
'Date' = [DateTime]::ParseExact($_.date, $fmt, $null)
'Severity' = $_.severity
'Hostname' = $_.hostname
'Message' = $_.'#cdata-section'
}
}
这篇关于解析类似 XML 的日志文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!