我正在编写一个脚本,将XML输出文件转换为具有特定格式的JSON文件。下面是要转换的XML输出。我在完成这项任务时遇到了问题,并且我在问底部脚本的哪些更改可以实现这一目标?
来自output.xml
的片段:
<System>
<tools>
<tool_PSList>
<process>
<process>
<pid>4188</pid>
<ownersid>"S-1-5-21-3556032652-3399990904-2739522603-1001"</ownersid>
<ownername>"Bochm"</ownername>
<ownerdomain>"DESKTOP-LS0HCH3"</ownerdomain>
-<file>
<name>"C:\ProgramFiles\WindowsApps\Microsoft.Messaging_1.10.22012.0_x86__8wekyb3d8bbwe\SkypeHost.exe"</name>
<size>44032</size>
<attr str="ARCHIVE" hex="0x20"/>
<cert_exists>"FALSE"</cert_exists>
<cert_verified>"FALSE"</cert_verified>
<cert_result>"TRUST_E_NOSIGNATURE"</cert_result>
<cert_comment>"The file is not signed"</cert_comment>
JSON输出所需的格式如下所示(idealoutput.json
,时间戳替换为脚本运行的时间):
{
"os": "win",
"ts": "timestamp here",
"value": "C:\\Program Files\\WindowsApps\\Microsoft.Messaging_1.10.22012.0_x86__8wekyb3d8bbwe\\SkypeHost.exe\"; cert_comment=\"The file is not signed\"
}
下面是我在当前状态下生成的当前脚本,不幸的是,这是我第一周使用PowerShell,XML和JSON。我可以包含下面我脚本中提到的其他文件,但我猜测有一种比导入格式更简单的方法,然后尝试用输出文件修改它,所以我没有在这里列出它。如果你想看到下面提到的其他XML文件,请告诉我,我很乐意帮忙。任何见解或建议将不胜感激!
#Puts output of crowdresponse in $xml
$xml = [xml](Get-Content -Path C:\Users\Bochm\Downloads\CrowdResponse\output.xml)
#Puts the formating in $format
$format = [xml](Get-Content -Path C:\Users\Bochm\Downloads\CrowdResponse\format.xml)
#Filters the output of crowdresponse into results
$result = $xml.system.tools.tool_PSList.processes.process.file |
Select-Object name, cert_comment
#adds the mac address to result
$result += $xml.system | Select-Object macv4
$cert_valid = $xml.system.tools.tool_PSList.processes.process.file | Where-Object {
$_.cert_signer -notmatch "Microsoft Corporation" -and
$_.cert_signer -notmatch "Microsoft Windows" -and
$_.cert_comment -match "The file is signed and the signature was verified"
} | Select-Object name, cert_comment
$cert_invalid = $xml.system.tools.tool_PSList.processes.process.file |
Where-Object { $_.cert_comment -match "The file is not signed" } |
Select-Object name, cert_comment
$node.innerXml += $cert_invalid.innerXml | Select-Object name, cert_comment
$result | ConvertTo-Json |
Out-File "C:\Users\Bochm\Downloads\CrowdResponse\output.json"
$cert_valid | ConvertTo-Json |
Out-File "C:\Users\Bochm\Downloads\CrowdResponse\certs_valid.json"
$cert_invalid | ConvertTo-Json |
Out-File "C:\Users\Bochm\Downloads\CrowdResponse\certs_invalid.json"
$node | Select-Object os, ts, value, 'text' | ConvertTo-Json |
Out-File "C:\Users\Bochm\Downloads\CrowdResponse\format.json"
后续问题代码:
$name = $xml.SelectNodes('//file') | ForEach-Object {
$_.cert_signer -notmatch "Microsoft Corporation" -and
$_.cert_signer -notmatch "Microsoft Windows" -and
$_.cert_comment -match "The file is signed and the signature was verified"
} | Select-Object cert_comment
$name = $xml.system.tools.tool_PSList.processes.process.file |
SelectNodes('//file') |
ForEach-Object {
$_.cert_signer -notmatch "Microsoft Corporation" -and
$_.cert_signer -notmatch "Microsoft Windows" -and
$_.cert_comment -match "The file is signed and the signature was verified"
} | Select-Object name
希望最终问题的代码:
$xml = Get-Content 'C:\Users\Bochm\Downloads\CrowdResponse\output.xml'
$name = $xml.system.tools.tool_PSList.processes.process.file| Where-Object {
$_.cert_signer -notmatch "Microsoft Corporation" -and
$_.cert_signer -notmatch "Microsoft Windows" -and
$_.cert_comment -match "The file is signed and the signature was verified"
} | ForEach-Object {
$prop = [ordered]@{
'os' = 'win'
'ts' = (Get-Date).DateTime
'value' = "{0}; cert_comment={1}" -f $_.name, $_.cert_comment
}
New-Object -Type PSCustomObject -Property $prop
} | Select-Object name
#$name = $xml.SelectSingleNode('//name').'#text'
$name = $xml.system.tools.tool_PSList.processes.process.file | Where-Object {
$_.cert_signer -notmatch "Microsoft Corporation" -and
$_.cert_signer -notmatch "Microsoft Windows" -and
$_.cert_comment -match "The file is signed and the signature was verified"
} | ForEach-Object {
$prop = [ordered]@{
'os' = 'win'
'ts' = (Get-Date).DateTime
'value' = "{0}; cert_comment={1}" -f $_.name, $_.cert_comment
}
New-Object -Type PSCustomObject -Property $prop
} | Select-Object cert_comment
$name = $xml.system.tools.tool_PSList.processes.process.file | Where-Object {
$_.cert_signer -notmatch "Microsoft Corporation" -and
$_.cert_signer -notmatch "Microsoft Windows" -and
$_.cert_comment -match "The file is signed and the signature was verified"
} | ForEach-Object {
$prop = [ordered]@{
'os' = 'win'
'ts' = (Get-Date).DateTime
'value' = "{0}; cert_comment={1}" -f $_.name, $_.cert_comment
}
New-Object -Type PSCustomObject -Property $prop
} | Select-Object name
$name = $xml.system.tools.tool_PSList.processes.process.file| Where-Object {
$_.cert_comment -match "The file is not signed"
} | ForEach-Object {
$prop = [ordered]@{
'os' = 'win'
'ts' = (Get-Date).DateTime
'value' = "{0}; cert_comment={1}" -f $_.name, $_.cert_comment
}
New-Object -Type PSCustomObject -Property $prop
} | Select-Object cert_comment
$name = $xml.system.tools.tool_PSList.processes.process.file| Where-Object {
$_.cert_comment -match "The file is not signed"
} | ForEach-Object {
$prop = [ordered]@{
'os' = 'win'
'ts' = (Get-Date).DateTime
'value' = "{0}; cert_comment={1}" -f $_.name, $_.cert_comment
}
New-Object -Type PSCustomObject -Property $prop
} | Select-Object name
#$name = $xml.SelectSingleNode('//name').'#text'
#$comment = $xml.SelectSingleNode('//cert_comment').'#text'
$prop = [ordered]@{
'os' = 'win'
'ts' = (Get-Date).DateTime
'value' = "$name; cert_comment=$comment"
}
New-Object -Type PSCustomObject -Property $prop | ConvertTo-Json | Out-File "C:\Users\Bochm\Downloads\CrowdResponse\end.json"
答案 0 :(得分:2)
我仍然不太清楚所需的转换是什么,因为您的XML示例格式不正确,输出JSON的3个属性中的2个似乎没有出现在其中。
假设你要提取<name>
和<cert_comment>
节点的内容并用OS和时间戳丰富它,你可以这样做:
[xml]$xml = Get-Content 'C:\path\to\output.xml'
$name = $xml.SelectSingleNode('//name').'#text'
$comment = $xml.SelectSingleNode('//cert_comment').'#text'
$prop = [ordered]@{
'os' = 'win'
'ts' = (Get-Date).DateTime
'value' = "$name; cert_comment=$comment"
}
New-Object -Type PSCustomObject -Property $prop | ConvertTo-Json
修改强>
$name = $xml.SelectNodes('//file') | ForEach-Object { $_.cert_signer -notmatch "Microsoft Corporation" -and $_.cert_signer -notmatch "Microsoft Windows" -and $_.cert_comment -match "The file is signed and the signature was verified" } | Select-Object cert_comment $name = $xml.system.tools.tool_PSList.processes.process.file | SelectNodes('//file') | ForEach-Object { $_.cert_signer -notmatch "Microsoft Corporation" -and $_.cert_signer -notmatch "Microsoft Windows" -and $_.cert_comment -match "The file is signed and the signature was verified" } | Select-Object name
这两个代码段不起作用。要过滤您需要Where-Object
的对象列表,而不是ForEach-Object
:
... | Where-Object {
$_.cert_signer -notmatch "Microsoft Corporation" -and
$_.cert_signer -notmatch "Microsoft Windows" -and
$_.cert_comment -match "The file is signed and the signature was verified"
} | ...
另外,您不想为$name
分配评论列表,但要创建自定义对象列表,因此您需要在ForEach-Object
循环中创建对象放在过滤器后面:
... | ForEach-Object {
$prop = [ordered]@{
'os' = 'win'
'ts' = (Get-Date).DateTime
'value' = "{0}; cert_comment={1}" -f $_.name, $_.cert_comment
}
New-Object -Type PSCustomObject -Property $prop
} | ...