簡體   English   中英

使用 powershell 腳本分析 XML 文件

[英]Analyse XML file with powershell script

我有一個 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的列表?

非常感謝

您發布的語句目前完全獨立 - 第一個輸出所有交易節點的文本編碼,第二個和第三個根本不做任何事情,因為此時$_不再具有分配給它的值.

要正確“連接”它們,您必須將過濾邏輯放在第一個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-Object cmdlet過濾來自Select-Xml的輸出:

$allTransactions |Where-Object {
  $_.Node.Response -eq 'Error'
} |ForEach-Object Messages

雖然這些建議可能會解決您的問題,但我強烈建議您不要這樣做- XPath 比您當前使用它的功能強大得多 :)


如何僅獲取響應為“錯誤”的事務?

我建議通過使用帶有Select-Xml的更准確的 XPath 表達式來簡化您的代碼——它可以准確地查找您想要的內容:

Select-Xml -Path C:\Users\user\path\path\file.xml -XPath '/Paths/Task/Transaction[Response = "Error"]'

是否有可能只將每個“錯誤”事務的第一個消息行作為輸出? 這樣我就有了一個錯誤交易中所有“Personal-Nr”的列表?

確定的事!

再一次,最簡單的方法是修改 XPath 表達式,這次只解析符合上述條件的<Transaction>下的第一個<Message>節點:

# 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM