Solution 1:

I'm doing exactly this in a script by way of PowerShell. The whole upload-to-database script is about 18K so I'm not going to repost the entire thing here (though I have the generic ideas here). Handling the XML is pretty simple.

The command to get the event data is what you already know.

wevtutil qe Security /r:$DC /q:"*[System[((EventID=$LogonID or EventID=$FLogonID or EventID=$LogoffID or EventID=$LockoutID) and TimeCreated[@SystemTime > '$LUFilterString'] and TimeCreated[@SystemTime < '$NowFilterString'] )]] " > $DC-events.xml

The variables in that should be clear. I'm tracking login, logout, and lockout events. Generating the "NowFilterString" in the funny format wevtutil requires:

$Now=get-date
$Msec=$now.Millisecond
$NowFilterString=$Now.AddSeconds(-1).AddMilliseconds(-$Msec).ToUniversalTime().ToString("O")

I'm truncating the milliseconds down to zero to better handle edge cases.

So now you have an XML file. Now what? To parse that XML file:

get-content ".\$DC-events.xml" | foreach {
    $Event=[xml]$_
    $DateTime=[datetime]$Event.event.System.TimeCreated.GetAttribute("SystemTime")
    codecodecodecode
}

Accessing individual elements is done by:

foreach ($Data in $Event.event.EventData.get_childNodes()) {
            if ($Data.Name -eq "TargetUserName") { $User=$Data."#text"}
            elseif ($Data.Name -eq "IpAddress") {$IP=$Data."#text"}
        }

Or another example

foreach ($Data in $Event.event.EventData.get_childNodes()) {
    if ($Data.Name -eq "TargetUserName") {$User=$Data."#text"}
       elseif ($Data.Name -eq "WorkstationName") {$MachineName=$Data."#text"}
       elseif ($Data.Name -eq "IpAddress") {$IP=$Data."#text"}
       # Ensure only failed logins to the right domain are processed:
       elseif ($Data.Name -eq "TargetDomainName") {$Domain=$Data."#text"}
    }

I hope this helps you figure out XML parsing. Since this is PowerShell, most of these are readily convertible to standard .NET calls.