使用 Excel VBS 分析 PowerShell PSCustomObject XML

Parsing a PowerShell PSCustomObject XML with Excel VBS

提问人:OldManWithTime 提问时间:11/2/2023 最后编辑:mklement0OldManWithTime 更新时间:11/3/2023 访问量:61

问:

我花了几个小时试图找到自己的解决方案,但失败了:( 我想做的就是读取 XML 并创建一个 Muti-Layered-Array 或 ArrayList。

这是 Powershell 的输出示例。

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>Selected.System.String</T>
      <T>System.Management.Automation.PSCustomObject</T>
      <T>System.Object</T>
    </TN>
    <MS>
      <I32 N="RefNum">1</I32>
      <S N="Name">MyVMName</S>
      <S N="Type">VM</S>
      <!-- Additional properties -->
    </MS>
  </Obj>
  <!-- Additional objects -->
</Objs>

这是众多尝试之一,但请随意将其拆开。

Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
xmlDoc.Async = False

' Load the PowerShell XML content
xmlDoc.Load "your_powershell_xml_file.xml"

If xmlDoc.ParseError = 0 Then
    ' Use the namespace in XPath queries
    xmlDoc.setProperty "SelectionNamespaces", "xmlns:ps='http://schemas.microsoft.com/powershell/2004/04'"

    ' Select all PSCustomObject elements
    Set customObjects = xmlDoc.SelectNodes("//ps:Obj[TN/T='System.Management.Automation.PSCustomObject']")

    ' Iterate through PSCustomObject elements
    For Each customObject In customObjects
        ' Access properties within the PSCustomObject
        RefNum = customObject.SelectSingleNode("MS/I32[@N='RefNum']").Text
        Name = customObject.SelectSingleNode("MS/S[@N='Name']").Text
        Type = customObject.SelectSingleNode("MS/S[@N='Type']").Text

        ' Display the parsed properties
        WScript.Echo "RefNum: " & RefNum
        WScript.Echo "Name: " & Name
        WScript.Echo "Type: " & Type
    Next
Else
    ' Handle XML parsing error
    WScript.Echo "Error loading PowerShell XML: " & xmlDoc.ParseError.Reason
End If

在 XML 中使用 VBS 读取的任何帮助 由 Powershell 制作并填充多层数组或 ArrayList。 在“xmlDoc.SelectNodes(”//ps:Obj[TN/T='System.Management.Automation.PSCustomObject']“)处失败

xml PowerShell XPath VBScript

评论

1赞 mklement0 11/2/2023
最终目标是填充 Excel 电子表格(请注意,Excel 使用的是 VBA,而不是 VBScript)?如果是这样,使用 PowerShell 可能会更容易,因为 PowerShell 本机理解 XML 格式 (CLIXML)。
1赞 Geert Bellekens 11/2/2023
“如果失败”是什么意思?你得到哪个错误?我认为你的xpath表达式是关闭的。
0赞 OldManWithTime 11/2/2023
我将把一些数据添加到工作表中。所以,我需要先摆弄它。失败的是 customObjects 在每个 中没有 customObject。它只是掉落
0赞 OldManWithTime 11/2/2023
XML 是一个主数据集,被更多的 PowerShell 程序使用,因此实际上无法更改它。我可以为此创建 CSV。但在这一点上,这是一个挑战。哈哈,这应该没有这么难..
1赞 OldManWithTime 11/3/2023
我想我需要做的就是找出正确的customObjects..但不确定如何调整“//ps:Obj[TN/T”我删除了 ps:但这无济于事。这就是我缺乏对 XML 的导航理解的地方

答:

2赞 mklement0 11/3/2023 #1

XPath 查询中的每个命名元素都必须使用相应的命名空间前缀

因此,例如,将:

Set customObjects = xmlDoc.SelectNodes("//ps:Obj[TN/T='System.Management.Automation.PSCustomObject']")

with(注意所有元素名称中的前缀):ps:

Set customObjects = xmlDoc.SelectNodes("//ps:Obj[ps:TN/ps:T='System.Management.Automation.PSCustomObject']")

这同样适用于后续调用。.SelectSingleNode()

总而言之:

Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
xmlDoc.Async = False

' Load the PowerShell XML content
xmlDoc.Load "C:\path\to\your\file.xml"

If xmlDoc.ParseError = 0 Then
    ' Use the namespace in XPath queries
    xmlDoc.SetProperty "SelectionNamespaces", "xmlns:ps='http://schemas.microsoft.com/powershell/2004/04'"

    ' Select all PSCustomObject elements
    Set customObjects = xmlDoc.SelectNodes("//ps:Obj[ps:TN/ps:T='System.Management.Automation.PSCustomObject']")

    ' Iterate through PSCustomObject elements
    For Each customObject In customObjects
        ' Access properties within the PSCustomObject
        refNumAttr = customObject.SelectSingleNode("ps:MS/ps:I32[@N='RefNum']").Text
        nameAttr = customObject.SelectSingleNode("ps:MS/ps:S[@N='Name']").Text
        typeAttr = customObject.SelectSingleNode("ps:MS/ps:S[@N='Type']").Text

        ' Display the parsed properties
        Wscript.Echo ("RefNum: " & refNumAttr)
        Wscript.Echo ("Name: " & nameAttr)
        Wscript.Echo ("Type: " & typeAttr)
    Next
Else
    ' Handle XML parsing error
    Wscript.Echo ("Error loading PowerShell XML: " & xmlDoc.ParseError.Reason)
End If

注意:

  • 若要在 Excel 的 Visual Basic for Application (VBA) 代码编辑器中运行代码,并将诊断输出到“即时窗口”,请替换为 。Wscript.EchoDebug.Print

评论

0赞 OldManWithTime 11/3/2023
那奏效了,非常感谢。我确实有一个 Id-10_t 问题。你怎么知道使用 ps:。我没有看到是否在 XML 路径中。
0赞 OldManWithTime 11/3/2023
是因为我在这里使用了它“xmlns:ps=”,所以我继续使用它吗?
0赞 mklement0 11/3/2023
@OldManWithTime:是的,这是因为你使用了 in,所以你必须在 XPath 查询中使用前缀。此前缀是自行选择的,不必与输入文档中的相同 - 只有 URI 必须相同。:psxmlDoc.setProperty "SelectionNamespaces", "xmlns:ps=..."ps:
0赞 OldManWithTime 11/3/2023
看起来XML没有遵循相同的格式。我试图粘贴它,但它看起来很糟糕,而且我超过了字符计数。第一个对象有'<TN RefId=“0”>',其余对象有'<TNRef RefId=“0”/>'我不确定你如何导航。
1赞 OldManWithTime 11/3/2023
哦,好吧,是时候进行 b 计划了。 哈哈,谢谢