如何使用 csv 列标题 powershell 获取 xml 字段值 [英] How to get xml field value using csv column header powershell

查看:33
本文介绍了如何使用 csv 列标题 powershell 获取 xml 字段值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用 for 循环然后在代码 ({ $_.'field_name' -eq $b} 中添加值 $b 时,它给出的是空值而不是结果.

When I use for loop and then add value $b here in code ({ $_.'field_name' -eq $b} then it's giving blank value instead of result.

$CSVpath = "G:\1.csv"
$columncount=((Get-Content $CSVpath)[0] -split ",").count
write-host $columncount
$xml= "G:\1.xml"
[xml] $xmlDoc = Get-Content $xml
for($i=0; $i -le $columncount;$i++){
$a = ((Get-Content $CSVpath)[0] -split(','))[$i]
$b= "'$a'"
Function xml{
param($value)
$xml= "G:\1.xml"
[xml] $xmlDoc = Get-Content $xml
$a1= $xmlDoc.enum_types.enum_type.Where({ $_.'field_name' -eq  $b}, 'First').items.item.where({ $_.id -eq 1}).value
$d = $a1.'#cdata-section'
write-host  $d
}
xml $b
}

请帮我解决问题.请找到xml:

Please help me to resolve issue. Please find xml:

    <enum_types>
    
        <enum_type field_name="Test1">
            <items>
                <item>
                    <id>1</id>
                    <value>A</value>
                </item>
            </items>
            </enum_type>
<enum_type field_name="Test2">
            <items>
                <item>
                    <id>1</id>
                    <value>A</value>
                </item>
            </items>
            </enum_type>
        </enum_types>

请找到 csv 文件:

Please find csv file :

推荐答案

这是您的代码的简化版本:

Here's a streamlined version of your code:

$CSVpath = "G:\1.csv"
$xmlPath = "G:\1.xml"

# This is a more robust (and faster) way to load XML files.
($xmlDoc = [xml]::new()).Load((Convert-Path $xmlPath))

# Get all column names
$columnNames = (Get-Content -First 1 $CSVpath) -split ',' -replace '"'
Write-Host "Column count: $($columnNames.Count); names: $columnNames"

foreach ($columnName in $columnNames) {
  @($xmlDoc.enum_types.enum_type.Where({ $_.field_name -eq $columnName }, 'First').
   items).ForEach({ $_.item }).Where({ $_.id -eq 1 }).value
}

它为我输出以下内容:

Column count: 2; names: Test1 Test2
A
A

注意:

  • 由于您的 XML 文档中没有 CDATA 部分,因此不需要 .'#cdata-section'

使用 .ForEach() 来枚举名为 的子元素的基本原理,特别是 - 虽然对于您的示例 XML 文档并不是绝对必要的,因为只有一个这样的子元素 - 在这个答案中进行了解释.

The rationale for using .ForEach() to enumerate the child elements named <item>, specifically - while not strictly necessary with your sample XML document, since there's only one such child element - is explained in this answer.

  • @(...) 的使用,array-subexpression operator,以便应用.ForEach()(和 .Where()) 安全仅在 Windows PowerShell 中是必需的,这是由于一个不幸的错误[1],该错误已在 PowerShell (Core) 7+ 中得到修复.

  • Use of @(...), the array-subexpression operator, in order to apply .ForEach() (and .Where()) safely is only required in Windows PowerShell, due to an unfortunate bug[1], which has since been fixed in PowerShell (Core) 7+.

链接的答案还显示了一个更快的基于 XPath 的解决方案,通过 Select-Xml,您可以类似地将其应用于内存中已经存在的 [xml] 实例 ($xmlDoc 在这种情况下),通过其 .SelectSingleNode() 实例方法.

The linked answer also shows a - faster - XPath-based solution, via Select-Xml, which you could apply analogously to an [xml] instance already in memory ($xmlDoc in this case), via its .SelectSingleNode() instance method.

以上仅对 CSV 文件的列名进行操作,带有 hard-coded id 值 - 就像您自己的尝试.

The above only operates on the column names of the CSV file, with a hard-coded id value - as in your own attempt.

根据 CSV 中的数据并根据填充的列从 XML 中提取数据:

To extract data from the XML based on the data in the CSV and based on which columns are filled in:

$CSVpath = "G:\1.csv"
$xmlPath = "G:\1.xml"

# This is a more robust (and faster) way to load XML files.
($xmlDoc = [xml]::new()).Load((Convert-Path $xmlPath))

# Import the CSV.
$csvRows = Import-Csv $CSVpath
# Get the column names.
$columnNames = $csvRows[0].psobject.Properties.Name

foreach ($csvRow in $csvRows) {
  foreach ($columnName in $columnNames) {
    $id = $csvRow.$columnName
    if (-not $id) { continue }
    @($xmlDoc.enum_types.enum_type.Where({ $_.field_name -eq $columnName }, 'First').
      items).ForEach({ $_.item }).Where({ $_.id -eq $id }).value
  }
}

注意:对于这样的嵌套循环,绝对值得考虑使用 .SelectSingleNode() 切换到 XPath 解决方案以提高性能.

Note: With a nested loop like that it's definitely worth considering switching to an XPath solution with .SelectSingleNode() in order to improve performance.

[1] .ForEach().Where() 应该适用于任何对象,甚至标量(非集合),但在 Windows PowerShell 中无法处理某些类型,例如 XML 元素.

[1] .ForEach() and .Where() should work on any object, even scalar (non-collection) ones, but in Windows PowerShell that doesn't work with certain types, such as XML elements.

这篇关于如何使用 csv 列标题 powershell 获取 xml 字段值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆