PowerShell XML 导出到 CSV - 无法获得一些子值

Posted

技术标签:

【中文标题】PowerShell XML 导出到 CSV - 无法获得一些子值【英文标题】:PowerShell XML export to CSV - can't get some child value 【发布时间】:2020-01-15 15:35:27 【问题描述】:

我有这个 XML 样式文件。

<?xml version="1.0" encoding="UTF-8" ?>
    <searchresults timestamp='ttt' www='www' qqq='qqq' url='url'>
        <obj id='00001' type='Random' name1='Mow' class='Data' >
            <tags>
                <tag key="Car" value="4x4" />
                <tag key="City" value="Big" />
                <tag key="Dog" value="Loud" />
            </tags>
            <details>
                <name desc="fulldesc">Full description</name>
            </details>
            <i1>Empty</i1>
            <i2>False</i2>
            <i3>True</i3>
        </obj>
        <obj id='00002' type='Random' name1='AGP' class='BigData' >
            <tags>
                <tag key="Car" value="Broken" />
                <tag key="City" value="Fresh" />
                <tag key="Dog" value="Long" />
            </tags>
            <details>
                <name desc="fulldesc">Good desc</name>
            </details>
            <i1>True</i1>
            <i2></i2>
            <i3>False</i3>
        </obj>
    </searchresults>

我需要将所有内容导出到 CSV。特别是我需要来自标签和详细信息容器的数据。在这个子节点中,信息有这样的方案——键和值。我需要make(键必须是-列名)(值必须是-键列值)。 (fulldesc = 列名,“完整描述” - fulldesc 列的内容) 像这样

id type name class Car City Dog fulldesc i1 i2 i3 -- ---- ---- ----- ---- ---- ---- -------- -- -- -- id1 type1 name1 class1 4x4 Big Loud 完整描述 Information1 Information2 Information3 id2 type2 name2 class2 4x4 Big Loud 完整描述 Information1 Information2 Information3

我使用此代码进行导出 - 它工作得很好,但我无法从 XML 中获取一些内容。

[xml]$inputFile = Get-Content ".\xmlFile.xml"
$inputFile.searchresults.ChildNodes |
    Export-Csv ".\xmlFile.csv" -NoTypeInformation -Delimiter:";" -Encoding:UTF8
Import-Csv -Delimiter ';' -Encoding:UTF8 -Path ".\xmlFile.csv" | Format-Table

结果:

id type name class tags details i1 i2 i3 -- ---- ---- ----- ---- -------- -- -- -- id1 type1 name1 class1 System.Xml.XmlElement System.Xml.XmlElement Information1 Information2 Information3 id2 type2 name2 class2 System.Xml.XmlElement System.Xml.XmlElement Information1 Information2 Information3

在标签和详细信息列中没有内容。

当我使用这段代码时:

[xml]$xml = Get-Content .\XML\12.xml
$xml.SelectNodes("//*")

我从 XML 接收所有信息:

时间戳:ttt 万维网:万维网 QQ : QQ 网址:网址 对象:对象,对象 编号:00001 类型:随机 名称1:割草 类:数据 标签:标签 细节:细节 i1 : 空的 i2:错误 i3 : 真 标签:标签,标签,标签 关键:汽车 价值:4x4 关键:城市 价值:大 关键:狗 价值:响亮 名称:名称 描述:全描述 #text : 完整描述 #text : 空 #文本:错误 #文本:真 编号:00002 类型:随机 名称1:AGP 类:大数据 标签:标签 细节:细节 i1:真 我2: i3:错误 标签:标签,标签,标签 关键:汽车 价值:破碎 关键:城市 价值:新鲜 关键:狗 值:长 名称:名称 描述:全描述 #text : 很好的描述 #文本:真 名称:i2 本地名称:i2 命名空间URI: 字首 : 节点类型:元素 父节点:对象 所有者文档:#document IsEmpty : 假 属性 : 有属性:假 架构信息:System.Xml.XmlName 内部Xml: 内文: 下一个兄弟姐妹:i3 上一个兄弟姐妹:i1 价值 : 子节点: 第一个孩子 : 最后一个孩子 : HasChildNodes:假 IsReadOnly : 假 外部Xml: 基础URI: 上一篇: #文本:错误

【问题讨论】:

相关:Convert XML to CSV automatically in Powershell 或 similar one 节点&lt;tags&gt;&lt;details&gt; 包含结构化信息。您需要在代码中定义您希望如何将其转换为字符串。您可以使用calculated properties 来实现。 【参考方案1】:

如果您愿意硬编码 CSV 列名和列数,您可以使用calculated properties,正如Ansgar Wiechers 建议的那样:

# Read the input file into an XML DOM.
[xml] $xml = Get-Content -Raw ".\xmlFile.xml"

# Loop over all <obj> children of <searchresults>
$xml.searchresults.obj | Select-Object id, type, name1, class, 
  @ n='Car'; e = $_.tags.tag[0].value , 
  @ n='City'; e = $_.tags.tag[1].value , 
  @ n='Dog'; e = $_.tags.tag[2].value , 
  @ n='desc'; e = $_.details.name.'#text' , 
  i1, i2, i3 |
    Export-Csv ".\xmlFile.csv" -NoTypeInformation -Delimiter ";" -Encoding:UTF8   

如果列名必须从 XML 文档属性和元素名动态派生,和/或 列数是变量

注意:

对于给定的输入 XML 文档,您需要确保至少 first 输出对象具有您想要 CSV 的 所有 属性(列)要包含的文件。它是第一个锁定输出列的对象。

为了不对列的名称和数量做出预先假设,下面的解决方案添加了在 XML 文档中找到的属性,这意味着输出 CSV 列排序,这意味着:

您必须依赖包含相同属性集/子元素集的所有 &lt;obj&gt; 元素变成列,或者使用 maximum 集预填充 $properties 哈希表输出列数,如果已知

否则,如果要更改输出列的顺序,则需要额外的逻辑。

# Read the input file into an XML DOM.
[xml] $xml = Get-Content -Raw ".\xmlFile.xml"

# Loop over all <obj> children of <searchresults>
$xml.searchresults.obj | ForEach-Object 

  $el = $_  # The input element at hand.

  # Initialize an ordered hashtable in which to collect / construct the properties
  # to send to the CSV file.
  $properties = [ordered] @

  # Loop over all attributes / children of the given <obj>
  foreach ($propName in ($el | Get-Member -Type Property).Name) 

    switch ($propName) 
      'tags' 
        # Instead of a single 'tags' property, create individual properties
        # based on the keys and values of the <tag> elements.
        foreach ($child in $el.tags.tag) 
          $properties.($child.Key) = $child.Value    
        
        break
      
      'details' 
        # Instead of a 'details' property,  use the <name> element's
        # 'desc' attribute value as the property name and assign it
        # the element's content.
        $properties.($el.$_.name.desc) = $el.$_.name.'#text'
        break
      
      default 
        # All other properties: pass them through.
        $properties.$propName = $el.$propName 
      
    

  

  # Output the ordered hashtable as a custom object, whose property names will become 
  # the CSV column headers and whose values will become the row values.
  [pscustomobject] $properties

 | Export-Csv ".\xmlFile.csv" -NoTypeInformation -Delimiter ";" -Encoding:UTF8

该方法的核心是$el | Get-Member -Type Property).Name,它从每个&lt;obj&gt;元素中提取所有属性名称,因为这些属性代表给定元素的属性和子元素。

这允许使用switch 语句对属性进行循环、传递或预处理。

【讨论】:

很高兴听到它有帮助,@DenisOr;我的荣幸。

以上是关于PowerShell XML 导出到 CSV - 无法获得一些子值的主要内容,如果未能解决你的问题,请参考以下文章

PowerShell:ConvertFrom-Json 将多个对象导出到 csv

运行多个 Powershell 命令并将结果导出到 csv

Powershell:将所有具有“NetworkRuleSet”属性的 Azure 存储帐户列出/导出到 CSV

powershell 功能 - 数据 - UI:将数据网格导出到CSV文件

使用Powershell将大输出从Oracle导出到CSV

powershell 将少于x个项目的列表导出到CSV文件