【问题标题】:Get data from XML elements as a table using Powershell使用 Powershell 从 XML 元素中获取数据作为表格
【发布时间】:2019-07-31 21:59:37
【问题描述】:

我尝试从 XML 元素中获取数据作为表格。下面的 XML 文件。 XML 文件是导出的防火墙配置。

<?xml version="1.0" encoding="UTF-8"?>
<fpc4:Root xmlns:fpc4="http://schemas.microsoft.com/isa/config-4" xmlns:dt="urn:schemas-microsoft-com:datatypes" StorageName="FPC" StorageType="0">
    <fpc4:Build dt:dt="string">7.0.9193.500</fpc4:Build>
    <fpc4:Comment dt:dt="string">0</fpc4:Comment>
    <fpc4:Edition dt:dt="int">32</fpc4:Edition>
    <fpc4:EnterpriseLevel dt:dt="int">2</fpc4:EnterpriseLevel>
    <fpc4:ExportItemClassCLSID dt:dt="string">{59740B3A-8771-492C-AF59-7764F4F939EF}</fpc4:ExportItemClassCLSID>
    <fpc4:ExportItemCompatibilityVersion dt:dt="int">4</fpc4:ExportItemCompatibilityVersion>
    <fpc4:ExportItemScope dt:dt="int">0</fpc4:ExportItemScope>
    <fpc4:ExportItemStorageName dt:dt="string">{A86DF49D-0078-48D5-8A58-A970482FA6D6}</fpc4:ExportItemStorageName>
    <fpc4:IsaXmlVersion dt:dt="string">9.0</fpc4:IsaXmlVersion>
    <fpc4:OptionalData dt:dt="int">0</fpc4:OptionalData>
    <fpc4:Upgrade dt:dt="boolean">0</fpc4:Upgrade>
    <fpc4:ConfigurationMode dt:dt="int">0</fpc4:ConfigurationMode>
    <fpc4:Arrays StorageName="Arrays" StorageType="0">
        <fpc4:Array StorageName="{7149EEA4-E267-43EA-A7C8-25C3FF1EC368}" StorageType="0">
            <fpc4:AdminMajorVersion dt:dt="int">0</fpc4:AdminMajorVersion>
            <fpc4:AdminMinorVersion dt:dt="int">0</fpc4:AdminMinorVersion>
            <fpc4:Components dt:dt="int">-1</fpc4:Components>
            <fpc4:DNSName dt:dt="string"/>
            <fpc4:Name dt:dt="string"/>
            <fpc4:Version dt:dt="string">0</fpc4:Version>
                <fpc4:Name dt:dt="string"/>
            <fpc4:RuleElements StorageName="RuleElements" StorageType="0">
                <fpc4:ComputerSets StorageName="ComputerSets" StorageType="0">
                    <fpc4:ComputerSet StorageName="{F51D0A66-40CA-4E1E-9454-A1F73834CEFC}" StorageType="2">
                        <fpc4:Name dt:dt="string">ScanSafe</fpc4:Name>
                        <fpc4:Computers StorageName="Computers" StorageType="2">
                            <fpc4:Computer StorageName="{9A946B36-12C6-484F-9729-97D51C53017D}" StorageType="2">
                                <fpc4:IPAddress dt:dt="string">100.93.231.200</fpc4:IPAddress>
                                <fpc4:Name dt:dt="string">1363.scans.net</fpc4:Name>
                            </fpc4:Computer>
                        </fpc4:Computers>
                    </fpc4:ComputerSet>
                    <fpc4:ComputerSet StorageName="{0598ED7C-CA3E-4461-A230-B2669B35872F}" StorageType="2">
                        <fpc4:Name dt:dt="string">Subscribers</fpc4:Name>
                        <fpc4:Computers StorageName="Computers" StorageType="2">
                            <fpc4:Computer StorageName="{1FF8B477-7DF2-4117-978A-044377B5958A}" StorageType="2">
                                <fpc4:IPAddress dt:dt="string">111.111.111.111</fpc4:IPAddress>
                                <fpc4:Name dt:dt="string">Client1</fpc4:Name>
                            </fpc4:Computer>
                            <fpc4:Computer StorageName="{43F2C2EB-BB08-4B2E-A05C-9D61E299820D}" StorageType="2">
                                <fpc4:IPAddress dt:dt="string">222.222.222.333</fpc4:IPAddress>
                                <fpc4:Name dt:dt="string">Client2</fpc4:Name>
                            </fpc4:Computer>
                            <fpc4:Computer StorageName="{6F1CA232-9C17-48B8-A794-65037301C24C}" StorageType="2">
                                <fpc4:IPAddress dt:dt="string">111.111.111.112</fpc4:IPAddress>
                                <fpc4:Name dt:dt="string">Client3</fpc4:Name>
                            </fpc4:Computer>
                        </fpc4:Computers>
                        <fpc4:AddressRanges StorageName="AddressRanges" StorageType="2">
                            <fpc4:AddressRange StorageName="{C7CD37CF-788B-45A0-9A44-2C0DA7C00D37}" StorageType="2">
                                <fpc4:IPFrom dt:dt="string">222.222.222.338</fpc4:IPFrom>
                                <fpc4:IPTo dt:dt="string">222.222.222.340</fpc4:IPTo>
                                <fpc4:Name dt:dt="string">Range 1 </fpc4:Name>
                            </fpc4:AddressRange>
                            <fpc4:AddressRange StorageName="{BC77F5FD-1CBF-4EDB-9968-2DD5ADA9090B}" StorageType="2">
                                <fpc4:IPFrom dt:dt="string">222.222.222.390</fpc4:IPFrom>
                                <fpc4:IPTo dt:dt="string">222.222.222.400</fpc4:IPTo>
                                <fpc4:Name dt:dt="string">Range 2</fpc4:Name>
                            </fpc4:AddressRange>
                        </fpc4:AddressRanges>
                    </fpc4:ComputerSet>
                </fpc4:ComputerSets>
            </fpc4:RuleElements>
        </fpc4:Array>
    </fpc4:Arrays>
</fpc4:Root>

我对以下元素中的数据感兴趣。

<fpc4:ComputerSet StorageName="{0598ED7C-CA3E-4461-A230-B2669B35872F}" StorageType="2">

到目前为止,我已经尝试过。关注

PS H:\> $XMLfile = 'C:\tmp\asd.xml'
[XML]$xml = Get-Content $XMLfile

$xml.Root.Arrays.Array.RuleElements.ComputerSets.ComputerSet.Item(1)

返回以下,我怎样才能让它在名称/计算机元素中显示数据?

StorageName   : {0598ED7C-CA3E-4461-A230-B2669B35872F}
StorageType   : 2
Name          : Name
Computers     : Computers
AddressRanges : AddressRanges
$xml.Root.Arrays.Array.RuleElements.ComputerSets.InnerText | Format-Table

将所有数据作为不可读的单个字符串返回。 |格式表不起作用。

我想在这样的表格中获取数据

Name            IPAddress             
Client1         111.111.111.111
Client2         222.222.222.333
Name            AddressRanges
Range 1         222.222.222.338 
                222.222.222.340
Range 2         222.222.222.390
                222.222.222.400

我认为 foreach 循环/循环会有所帮助,但目前我不知道该怎么做。

谢谢。

【问题讨论】:

    标签: xml powershell


    【解决方案1】:

    您需要两个循环,您可以在其中仅使用感兴趣的属性构造自定义对象,这既方便了以后的编程处理,又可以输出感兴趣的表格格式:

    # Read the XML file into a System.Xml.XmlDocument DOM ([xml]).
    $xml = [xml] (Get-Content -Raw 'C:\tmp\asd.xml')
    
    # Get a reference to the common parent element of the elements of interest.
    $parentEl = $xml.Root.Arrays.Array.RuleElements.ComputerSets.ComputerSet[1]
    
    # Loop over computers and create custom objects.
    $computers = foreach ($computer in $parentEl.Computers.Computer) { 
      [pscustomobject] @{ 
        Name = $computer.Name.InnerText
        IPAddress = $computer.IPAddress.InnerText 
      } 
    }
    
    # Loop over address ranges.
    $ranges = foreach ($range in $parentEl.AddressRanges.AddressRange) { 
      [pscustomobject] @{ 
         Name = $range.Name.InnerText
         AddressRange = $range.IPFrom.InnerText, $range.IPTo.InnerText
      } 
    }
    
    # For display, print the computers and range separately.
    $computers | Format-Table
    $ranges | Format-Table
    

    注意需要使用Format-Table单独;如果您同时将 两个 集合发送到 Format-Table ($computer, $ranges | Format-Table),则 first 集合中对象的属性将单独确定表列,因此您将'看不到第二个集合中对象独有的属性;也就是说,输出 $computer, $ranges 将按预期显示计算机,但会丢失范围的 AddressRange 属性值。

    请记住,Format-* cmdlet 只能用于创建 for-display 表示,不能用于进一步的编程处理;在手头的情况下,您可以使用$computers$ranges 作为后者。

    请注意,这同样适用于Out-File / &gt;:它们使用Format-* cmdlet隐式for-display 表示保存到文件中。 在本例中,由于输入对象的属性少于 4 个,因此隐式应用了 Format-Table

    因此,如果您想在单个输出文件中捕获两个用于显示的表格表示,您必须再次使用 individual 命令:

    $computers | Out-File -FilePath $out_file          # or: $computers >  $out_file
    $ranges    | Out-File -FilePath $out_file -Append  # or: $ranges    >> $out_file
    

    以上产出:

    Name    IPAddress
    ----    ---------
    Client1 111.111.111.111
    Client2 222.222.222.333
    Client3 111.111.111.112
    
    
    Name     AddressRange
    ----     ------------
    Range 1  {222.222.222.338, 222.222.222.340}
    Range 2  {222.222.222.390, 222.222.222.400}
    

    【讨论】:

      【解决方案2】:

      我建议使用,然后从那里使用成员访问运算符 (.):

      [xml]$xml = Get-Content -Path $xmlFile
      $computerSets = $xml.SelectNodes('//ComputerSets')
      
      foreach ($set in $computerSets) {
          $pcs = $set.Computers # => array of Computers
          $ips = $set.AddressRanges # => array of AddressRange
      }
      

      在每个集合的循环中以此类推。

      【讨论】:

      • OP 已经有了感兴趣的父元素;他们的困难在于有选择地从孩子那里提取数据并从中生成表格输出。请注意,您不能仅通过标记名称来提取名称空间限定的元素,就像您在 XPath 查询中建议的那样。
      • @mklement0 感谢您的反馈。我很高兴 XML 正在消亡;希望早点。命名空间令人头疼。
      • 同意;例如,.SelectNodes()stackoverflow.com/a/51379117/45375Select-Xml 稍微减轻了痛苦:stackoverflow.com/a/49387055/45375
      猜你喜欢
      • 2022-10-17
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-20
      • 1970-01-01
      • 1970-01-01
      • 2018-08-06
      相关资源
      最近更新 更多