我有一个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)如何删除不包含最大/最高日期的节点。
编辑:
另一种更简单的方法是:
使用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($_) }
}
}
这应该完全符合你的要求:
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 )