访问/过滤不带值的XML节点

时间:2018-11-20 13:56:44

标签: xml powershell filter

给出以下XML:

<?xml version="1.0"?>
<doc>
    <taskinformation>
        <taskrecord>
            <taskstatus>
               <complete/>
            </taskstatus>
            <tasknumber>000001</tasknumber>
            <taskduration>13</taskduration>
        </taskrecord>
        <taskrecord>
            <taskstatus>
               <pending/>
            </taskstatus>
            <tasknumber>000002</tasknumber>
        </taskrecord>
    </taskinformation>
</doc>

我已将数据加载为XML

$Testxml = new-object system.XML.XMLDocument
$Testxmlxml = [xml](Get-Content ".\test.xml")

如何分别访问状态为“待处理/” “完成/” 的所有任务,将其用管道传输,给出已完成和待处理的任务数,可能包含完成任务的总工时和平均工时?

我尝试了

$taskinformation.taskrecord | where $_.innerXml -Contains *complete*

但是没有用。任何帮助将不胜感激。


编辑: 另一个后续问题:为什么以下操作无效?

$xml.doc.taskinformation.taskrecord | where-object ($_.taskstatus.innerxml -like "complete")

2 个答案:

答案 0 :(得分:0)

一些XPath可以帮助您。

$x = [xml]@'
<?xml version="1.0"?>
<doc>
    <taskinformation>
        <taskrecord>
            <taskstatus>
               <complete/>
            </taskstatus>
            <tasknumber>000001</tasknumber>
            <taskduration>13</taskduration>
        </taskrecord>
        <taskrecord>
            <taskstatus>
               <pending/>
            </taskstatus>
            <tasknumber>000002</tasknumber>
        </taskrecord>
        <taskrecord>
            <taskstatus>
               <complete/>
            </taskstatus>
            <tasknumber>000003</tasknumber>
            <taskduration>14</taskduration>
        </taskrecord>
    </taskinformation>
</doc>
'@
($t = $x.SelectNodes('//taskrecord/taskstatus/*[self::complete|self::pending]/../..')) |
  Where-Object { $_.taskstatus.ChildNodes[0].Name -eq 'complete' } |
  ForEach-Object { $_.taskduration } | Measure-Object -Average -Sum |
  Select @{ Name='TotalCount'; Expression={$t.Count} }, Average, Sum |
  Format-Table -AutoSize

TotalCount Average Sum
---------- ------- ---
         3    13,5  27

答案 1 :(得分:0)

这是我的尝试。这不仅会输出计数结果,还会输出任务本身:

# I faked loading the xml from file using '$xml = [xml](Get-Content ".\test.xml")'
$xml = [xml]@"
<?xml version="1.0"?>
<doc>
    <taskinformation>
        <taskrecord>
            <taskstatus>
               <complete/>
            </taskstatus>
            <tasknumber>000001</tasknumber>
            <taskduration>13</taskduration>
        </taskrecord>
        <taskrecord>
            <taskstatus>
               <complete/>
            </taskstatus>
            <tasknumber>000005</tasknumber>
            <taskduration>124</taskduration>
        </taskrecord>        
        <taskrecord>
            <taskstatus>
               <pending/>
            </taskstatus>
            <tasknumber>000002</tasknumber>
        </taskrecord>
    </taskinformation>
</doc>
"@

$report = "" | Select-Object Pending,Completed,AverageDuration,TotalDuration
$result = @()
$xml.doc.taskinformation.taskrecord | ForEach-Object {
    if ($_.taskstatus.innerXml -like '*complete*') {
        #$countComplete++
        $report.Completed++
        $report.TotalDuration += [double]$_.taskduration
        #$totalDuration += [int]$_.taskduration
        $result += [PSCustomObject]@{
            TaskNumber   = $_.tasknumber
            TaskDuration = $_.taskduration
            TaskStatus   = 'Completed'
        }
    }
    elseif ($_.taskstatus.innerXml -like '*pending*') {
        #$countPending++
        $report.Pending++
        $result += [PSCustomObject]@{
            TaskNumber   = $_.tasknumber
            TaskDuration = ''
            TaskStatus   = 'Pending'
        }
    }
}
# outout the results
$result | Sort-Object TaskNumber | Format-Table -AutoSize
if ($report.Completed) {
    $report.AverageDuration = $report.TotalDuration / $report.Completed
}
$report | Format-Table -AutoSize

其输出将是:

TaskNumber TaskDuration TaskStatus
---------- ------------ ----------
000001     13           Completed 
000002                  Pending   
000005     124          Completed 



Pending Completed AverageDuration TotalDuration
------- --------- --------------- -------------
      1         2            68,5           137