我有一個 xml 日志檔案。該檔案如下所示:
<Transaction name='0' id='1'>
<Response>Warning</Response>
<Statistic mode='Element'>
<Information>0</Information>
<Warning>0</Warning>
<Error>0</Error>
</Statistic>
<Messages>
<Message state='Warning'>Personal-Nr.: 12345, Tom Test</Message>
<Message state='Warning'>This is a warning message 1</Message>
<Message state='Warning'>This is a warning message 2</Message>
<Message state='Warning'>This is a warning message 3</Message>
<Message state='Warning'>This is a warning message 4</Message>
</Messages>
</Transaction>
這種模式重復大約 900 次,有時會有更多或更少的訊息。現在我只想獲取<Response>Error</Response>發生的所有事務。
所以我在 Powershell 中撰寫了這段代碼:
## parsing xml file and opening inner node
Select-Xml -Path C:\Users\user\path\path\file.xml -XPath '/Paths/Task/Transaction' | ForEach-Object { $_.Node.InnerXML }
## looping through Response set with include="Error"
$_.Node.InnerXML | Where-Object Response -eq 'Error' | ForEach-Object { $_.Messages }
echo $_.Messages
但我得到的唯一資料是所有交易,無論回應是Warning還是Error。更進一步,我是否只離開Select-Xml線路并洗掉其余線路甚至都沒有關系。結果總是一樣的。我總是得到所有的回應。
所以我的問題是:我如何才能只獲得 Response 所在的交易Error?
額外問題:是否有可能只將每筆Error交易的第一條訊息行作為輸出?這樣我就有了Personal-Nr一個錯誤交易中所有的串列?
非常感謝
uj5u.com熱心網友回復:
您發布的陳述句目前是完全獨立的 - 第一個輸出所有交易節點的文本編碼,第二個和第三個根本不做任何事情,因為$_此時不再有分配給它的值。
要正確“連接”它們,您必須將過濾邏輯放在第一個ForEach-Object塊內,例如:
Select-Xml ... |ForEach-Object {
if($_.Node.Response -eq 'Error'){ $_.Messages }
}
...或將每個步驟的輸出存盤在臨時變數中,例如:
$allTransactions = Select-Xml ... -XPath '//Transaction'
$allTransactions |ForEach-Object {
if($_.Node.Response -eq 'Error'){ $_.Messages }
}
我應該指出這ForEach-Object { if(...){ $_ } }是一種反模式,除非您的代碼具有更復雜的副作用 - 更慣用的解決方案是呼叫Where-Objectcmdlet 來過濾來自以下內容的輸出Select-Xml:
$allTransactions |Where-Object {
$_.Node.Response -eq 'Error'
} |ForEach-Object Messages
雖然這些建議可能會解決您的問題,但我強烈建議您不要這樣做- XPath比您當前使用它的功能強大得多 :)
如何僅獲取回應為“錯誤”的事務?
我建議通過使用更準確的XPath 運算式來簡化您的代碼Select-Xml- 一個查找您想要的內容的運算式:
Select-Xml -Path C:\Users\user\path\path\file.xml -XPath '/Paths/Task/Transaction[Response = "Error"]'
是否有可能只將每個“錯誤”事務的第一個訊息行作為輸出?這樣我就有了一個錯誤交易中所有“Personal-Nr”的串列?
確定的事!
再一次,最簡單的方法是修改 XPath 運算式,這次只決議符合上述條件的第一個 <Message>節點:<Transaction>
# beware that index selectors in XPath start at 1, not 0
//Transaction[Response = "Warning"]/Messages/Message[1]
但這還不是全部!XPath 有幾個有用的功能——所以我們可以更深入地為我們XPath提取和解碼訊息文本!
//Transaction[Response = "Warning"]/Messages/Message[1]/text()
這將導致Select-Xml回傳一個由XmlText實體組成的節點集,您可以將其直接轉換為字串以獲取原始字串內容。
將其與 重新組合在一起Select-Xml,您最終會得到如下結果:
$filePath = 'C:\Users\user\path\path\file.xml'
$xPath = '//Transaction[Response = "Warning"]/Messages/Message[1]/text()'
$messages = Select-Xml -Path $filePath -XPath $xPath |ForEach-Object ToString
$messages
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/484388.html
上一篇:是假用堆記憶體共享案例嗎?
