Powershell XML操作:仅保留日期最大的节点

问题描述 投票:0回答:2

我有一个XML文件,具有以下(简化)结构:

<XML>
    <Observation>
       <Dimension value="2018-11-01" />
       <Value value="123" />
    </Observation>
    <Observation>
       <Dimension value="2018-11-02" />
       <Value value="456" />
    </Observation>
    <Observation>
       <Dimension value="2018-12-01" />
       <Value value="789" />
    </Observation>
    <Observation>
       <Dimension value="2018-12-02" />
       <Value value="222" />
    </Observation>
</XML>

手头的任务是删除value节点的Dimension属性中的日期不是最大日期的节点。或者换句话说:只应保留value节点的Dimension属性中包含最大/最高日期的节点。这应该每个月完成。

因此,结果应如下所示:

<XML>
    <Observation>
       <Dimension value="2018-11-02" />
       <Value value="456" />
    </Observation>
    <Observation>
       <Dimension value="2018-12-02" />
       <Value value="222" />
    </Observation>
</XML>

怎么能在Powershell中完成?我知道如何读取XML文件以及如何进行基于XPath的查询:

$doc.SelectNodes("//Observation", $ns)

但是,我不知道如何a)确定每月的最大/最高日期,以及b)如何删除不包含最大/最高日期的节点。

编辑:

另一种更简单的方法是:

  1. 找到每月的最高/最高天数
  2. 仅保留具有此日期的节点。
xml powershell data-manipulation
2个回答
1
投票

使用Group-Object按月分组简化了流程。

$doc.XML.Observation | Group-Object { $_.Dimension.value.Substring(0,7) } | foreach {
    $_.Group | Sort-Object { $_.Dimension.value } -Descending |
    Select-Object -Skip 1 | foreach { $doc.XML.RemoveChild($_) }
}

以下是对应于存在多个父节点的情况的方法。

$doc.SelectNodes("//message:DataSet/generic:Series", $ns) | foreach {
    $_.SelectNodes("./generic:Obs", $ns) | Group-Object { $_.ObsDimension.value.Substring(0,7) } | foreach {
        $_.Group | Sort-Object { $_.ObsDimension.value } -Descending |
        Select-Object -Skip 1 | foreach { $_.ParentNode.RemoveChild($_) }
    }
}

0
投票

这应该完全符合你的要求:

Add-Type -AssemblyName System.Collections

$filePath   = "inputfile.xml"
$filePath1  = "outputfile.xml"

$xmlContent = New-Object System.Xml.XmlDocument
$xmlContent.PreserveWhitespace = $true
$xmlContent = [xml]([System.IO.File]::ReadLines($filePath))

[System.Collections.Generic.List[string]]$highestValues = @()

$oldMonth = ""
$oldYear  = ""

$xmlContent.XML.Observation.Dimension | Sort-Object { $_.value }  -Descending | ForEach-Object {

    $currentDate  = $_.value
    $currentYear  = $currentDate.Substring(0,4)
    $currentMonth = $currentDate.Substring(5,2)

    if( $currentYear -ne $oldYear -or $currentMonth -ne $oldMonth ) {
        $oldYear  = $currentYear
        $oldMonth = $currentMonth
        $highestValues.Add( $currentDate )
    }
}

$numItems   = ($xmlContent.XML.Observation.Dimension).Count

for( $i = $numItems - 1; $i -ge 0; $i-- ) {

    if( !$highestValues.Contains( $xmlContent.XML.Observation.Dimension[$i].value ) ) {
        [void]$xmlContent.XML.RemoveChild( $xmlContent.XML.Observation[$i] )
    }

}

[void]$xmlContent.Save( $filePath1 )
© www.soinside.com 2019 - 2024. All rights reserved.