【问题标题】:How to get xml field value using csv column header powershell如何使用csv列标题powershell获取xml字段值
【发布时间】:2021-08-26 03:41:31
【问题描述】:

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

$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:

    <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 文件:

【问题讨论】:

    标签: xml powershell command-line-interface


    【解决方案1】:

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

    $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() 枚举名为&lt;item&gt; 的子元素的基本原理,特别是 - 虽然对于您的示例 XML 文档并非绝对必要,因为只有 一个 这样的子元素 - 在this answer.

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

      • 链接的答案还显示了一个 - 更快 - 基于 XPath 的解决方案,通过 Select-Xml,您可以类似地应用到内存中的 [xml] 实例(在本例中为 $xmlDoc),通过其 .SelectSingleNode()实例方法。


    以上内容仅对 CSV 文件的列名进行操作,并使用 硬编码 id 值 - 就像您自己的尝试一样。

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

    $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 解决方案以提高性能。

    [1] .ForEach().Where() 应该适用于 any 对象,甚至是 scalar(非集合)对象,但在 Windows PowerShell 中不适用于某些类型,例如 XML 元素。

    【讨论】:

      猜你喜欢
      • 2021-03-25
      • 1970-01-01
      • 2021-08-09
      • 1970-01-01
      • 2018-11-15
      • 1970-01-01
      • 2014-07-27
      • 2012-08-26
      相关资源
      最近更新 更多