【问题标题】:XML Parent and Child Attributes and Elements in PowerShellPowerShell 中的 XML 父子属性和元素
【发布时间】:2013-06-28 02:16:01
【问题描述】:

我有一些 XML 数据,其中包含许多属性和多个同名元素,我想将其展平为 CSV 文件。数据 XML 如下所示:

<?xml version="1.0" encoding="utf-8"?>
<SEGMENTS>
    <SEGMENT NAME="webcluster">
        <RESULTPAGE>
            <RESULTSET FIRSTHIT="1" LASTHIT="100" HITS="100" TOTALHITS="100">
                <HIT NO="1" RANK="19000" SITEID="0" MOREHITS="100">
                    <FIELD NAME="rank">19000</FIELD>
                    <FIELD NAME="id">1</FIELD>
                    <FIELD NAME="url">C:\website.com\folder1\file1.txt</FIELD>
                    <FIELD NAME="filename">file1.txt</FIELD>
                    <FIELD NAME="path">https://website.com/folder1/</FIELD>
                </HIT>
                <HIT NO="2" RANK="19000" SITEID="0" MOREHITS="100">
                    <FIELD NAME="rank">19000</FIELD>
                    <FIELD NAME="id">2</FIELD>
                    <FIELD NAME="url">C:\website.com\folder1\file2.txt</FIELD>
                    <FIELD NAME="filename">file2.txt</FIELD>
                    <FIELD NAME="path">https://website.com/folder1/</FIELD>
                </HIT>
                <HIT NO="3" RANK="18999" SITEID="0" MOREHITS="100">
                    <FIELD NAME="rank">18999</FIELD>
                    <FIELD NAME="id">3</FIELD>
                    <FIELD NAME="url">C:\website.com\folder5\file3.txt</FIELD>
                    <FIELD NAME="filename">file3.txt</FIELD>
                    <FIELD NAME="path">C:\website.com\folder\</FIELD>
                </HIT>
            </RESULTSET>
        </RESULTPAGE>
    </SEGMENT>
</SEGMENTS>

我正在尝试迭代它以产生类似的东西

HIT    filename    path  
-----  ----------  ------  
1      file1.txt   C:\website.com\folder1\  
2      file2.txt   C:\website.com\folder1\  
3      file3.txt   C:\website.com\folder5\

我的代码是:

[xml]$xml=Get-Content .\xmlfile.xml  
$hits = $xml.segments.segment.resultpage.resultset.hit  
foreach($hit in $hits)  
{  
    foreach($field in $hit.field)  
    {  
        if (field."NAME" -eq 'url')  
        {  
            write-output $hit.no $field."#VALUE"  
        }  
    }  
}  

而且我不断收到错误。我可以通过按序号位置 ($hits[0].field[4]) 引用它们来访问不同的元素和属性,但我想防止将来输出 FIELD 值的顺序可能不同。

谁能建议我如何完成这项工作?我尝试使用 select-XML,发现它更麻烦,但也许这是更优雅的方法。

【问题讨论】:

    标签: xml powershell


    【解决方案1】:

    这样的事情似乎可以做到,虽然我不喜欢那样。

    [xml]$xml=Get-Content .\xmlfile.xml  
    $hits = $xml.segments.segment.resultpage.resultset.hit  
    foreach($hit in $hits)  
    {  
        $result = new-object PSObject -Property @{ hit = $hit.no; filename = ""; path = ""}
    
        foreach($field in $hit.field)  
        {  
            if ($field."NAME" -eq 'url')  
            {  
                $result.path = $field."#text"
            }  
            if ($field."NAME" -eq 'filename')
            {
                $result.filename = $field."#text"
            }
        }  
        write-output $result
    }  
    

    或者,只是抓取所有字段,然后选择相关:

    [xml]$xml=Get-Content .\xmlfile.xml  
    $hits = $xml.segments.segment.resultpage.resultset.hit  
    foreach($hit in $hits)  
    {  
        $result = new-object PSObject -Property @{ hit = $hit.no }
        $hit.field | % { Add-Member -InputObject $result -MemberType NoteProperty -Name $_."NAME" -Value $_."#text"}  
        $result | select hit,url,filename | write-output
    }  
    

    【讨论】:

    • 这成功了!谢谢!有人离线建议:[xml]$hitfile = Get-Content fastxml.xml foreach($hit in $hitfile.segments.segment.resultpage.resultset.hit) { $row = $mjatable.NewRow() ` $row.Hit = $hit.No ` $row .InternalID = $hit.field | ?{$_.name -eq 'Internalid'} | foreach {$_.'#text'} ` $row.URL = $hit.field | ?{$_.name -eq 'url'} | foreach {$_.'#text'} ` $mjaTable.Rows.Add($row) } $mjaTable |格式表-AutoSize
    • 我仍然很好奇是否可以使用 NAME attrib = ("url" 或 "Internalid") 引用 FIELD 元素并在不使用 WHERE-OBJECT 过滤器的情况下检索“#text”值,但是如果没有,这两个解决方案可以完成工作。再次感谢!
    【解决方案2】:

    试试这样的:

    Select-Xml -Xml $xml -XPath '//HIT' | Foreach {
        $num=$_.Node.NO
        $filenameAttr = $_.Node.Field | where {$_.Name -eq 'filename'}
        $pathAttr = $_.Node.Field | where {$_.Name -eq 'path'}
        new-object psobject -Property ([ordered]@{HIT=$num; filename = $filenameAttr.InnerText; path = $pathAttr.InnerText})
    }
    

    【讨论】:

    • Keith,尝试上面的代码我得到:无法找到类型 [ordered]:确保已加载包含此类型的程序集。在 line:6 char:45 + new-object psobject -Property ([ordered]
    • 啊,这是 PowerShell V3 的新功能。您可以删除它,但创建的对象中的属性顺序将是随机的。
    【解决方案3】:

    结合方法。 Select 允许按特定顺序获取字段。

    [xml]$xml=Get-Content .\xmlfile.xml  
    $hits = $xml.segments.segment.resultpage.resultset.hit  
    foreach($hit in $hits)  
    {  
        $r = @{hit = $hit.no; url = "N/A";filename="N/A"}
        $hit.field | % { $r[$_."NAME"] = $_."#text" }  
        New-Object PSObject -Property $r | Select hit,url,filename
    }  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 2022-12-24
      相关资源
      最近更新 更多