PowerShell XML 导出为 CSV - 无法获取某些子值



>我有这个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 类型 名称类 汽车城 狗 富尔德斯克 i1 i2 i3 --  ----  ----  -----  ----   ----   ----    -------               --           --           -- ID1 类型1 名称1 类1 4x4 大声 完整描述信息1 信息2 信息3 id2 类型2 名称2 类2 4x4 大声 完整描述 信息1 信息2 信息3

我使用此代码进行导出 - 它工作得很好,但我无法从 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 类型 名称 类 标签 详细信息 i1 i2 i3 --  ----  ----  -----  ----                  -------               --           --           -- id1 类型1 名称1 类1 系统.Xml.Xml元素系统.Xml.Xml元素信息1 信息2 信息3 id2 类型2 名称2 类2 系统.Xml.Xml元素系统.Xml.Xml元素信息1 信息2 信息3

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

当我使用此代码时:

[xml]$xml = Get-Content .XML12.xml
$xml.SelectNodes("//*")

我从 XML 接收所有信息:

时间戳 : TTT 万维网 : 万维网 QQQ : QQQ 网址 : 网址 obj : {obj, obj} 编号 : 00001 类型 : 随机 名称1 : 割草 类 : 数据 标签 : 标签 详情 : 详情 i1 : 空 i2 : 假 i3 : 真 标签 : {标签, 标签, 标签} 钥匙 : 汽车 值 : 4x4 密钥 : 城市 值 : 大 密钥 : 狗 值 : 响亮 名称 : 名称 描述 : 富尔德斯克 #text : 完整描述 #text : 空 #text : 假 #text : 真 编号 : 00002 类型 : 随机 名称1 : AGP 类 : 大数据 标签 : 标签 详情 : 详情 i1 : 真 i2 : i3 : 假 标签 : {标签, 标签, 标签} 钥匙 : 汽车 值 : 已损坏 密钥 : 城市 值 : 新鲜 密钥 : 狗 值 : 长 名称 : 名称 描述 : 富尔德斯克 #text : 良好的描述 #text : 真 产品中文名称 : i2 本地名称 : i2 命名空间 URI : 前缀: 节点类型 : 元素 父节点 : obj 所有者文件 : #document 是空的 : 假 属性 : {} 有属性 : 假 SchemaInfo : System.Xml.XmlName InnerXml : 内文本 : 下一个兄弟姐妹 : i3 上一页兄弟姐妹 : i1 价值: 子节点 : {} 第一个孩子 : 最后一个孩子 : HasChildNodes: False 只读 : 假 外部XML :基数 : 上一页文字 : #text : 假

如果您愿意对 CSV 列名以及列数进行硬编码,则可以使用计算属性,如 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 文档,您需要确保至少第一个输出对象具有您希望 CSV 文件包含的所有属性(列(。它是锁定输出列中的第一个对象。

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

    • 您必须依赖包含相同属性/子元素集的所有<obj>元素才能转换为列,或者使用最大输出列集(如果已知(预填充$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,它从每个<obj>元素中提取所有属性名称,因为这些属性表示给定元素的属性和子元素。

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

最新更新