Microsoft Sentinel · KQL Deep Dive
Stop fragile index-based XML parsing and switch to a universal, future-proof EventData parser that works across all Windows event types in Microsoft Sentinel.
⚡ If you’ve ever worked with the Event table in Microsoft Sentinel or Azure Monitor Logs, you already know the pain:
- EventData is XML and every event type uses a different schema.
- Most examples use fragile array indexes like
Data[7]['#text']. - This post gives you a universal KQL pattern that dynamically parses all
<Data>fields. - No index guessing, no hardcoding, and it works across multiple Event IDs.
Why the Usual Way of Parsing EventData Fails
Traditionally, analysts parse XML like this:
extend ThreatName = parse_xml(EventData).DataItem.EventData.Data[7]['#text']
Problems with this approach:
- Fragile – If Microsoft adds or reorders
<Data>fields, everything breaks. - Event-specific – Works only for one Event ID or one schema.
- Hard to maintain – Counting indexes destroys readability.
- Not scalable – You must rewrite the parser for each event type.
🔥 The Universal EventData XML Parser (KQL)
// Universal EventData XML parser for the Event table
Event
| where TimeGenerated >= ago(24h)
| extend ParsedEventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand ParsedEventData
| extend
FieldName = tostring(ParsedEventData['@Name']),
FieldValue = tostring(ParsedEventData['#text'])
| evaluate pivot(FieldName, any(FieldValue), TimeGenerated, Computer, EventID)
This query extracts every field inside EventData, automatically names columns using <Data Name="...">, works across all event IDs, and requires zero editing when the XML structure changes.
Optional: Wrap Into a Reusable Function
let parse_eventdata = (input:(TimeGenerated:datetime, Computer:string, EventID:int, EventData:string)) {
input
| extend ParsedEventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand ParsedEventData
| extend
FieldName = tostring(ParsedEventData['@Name']),
FieldValue = tostring(ParsedEventData['#text'])
| evaluate pivot(FieldName, any(FieldValue), TimeGenerated, Computer, EventID)
};
// Usage
parse_eventdata(Event | where TimeGenerated >= ago(1d))
Performance Tips
- Always use a time filter (e.g.,
ago(24h)or smaller). - Filter by
EventLogorEventIDbefore parsing where possible. - Avoid parsing months of raw
EventDataat once unless absolutely required.
Final Thoughts
This universal parser is one of the most powerful ways to work with Windows Event Logs in Microsoft Sentinel. It simplifies analysis, enhances detection engineering, and eliminates the brittle, outdated practice of index-based XML parsing.
If you work with Sentinel long enough, this quickly becomes one of your core KQL tools — something you reuse across detections, hunting queries, and incident investigations.
Need Expert Help with Microsoft Sentinel?
Whether you’re building detections, optimizing costs, or setting up your SOC — SecByte offers hands-on Microsoft Sentinel consultancy, training, and architecture support.

Leave a Reply