Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select top 10 events from wevtutil using xpath

Tags:

xpath

I am currently working on a project that uses the Windows event log. I am using wevtutil to get the results from the event logs. I know that wevtutil supports xpath queries, but since I'm new to xpath I don't know that I can achieve what I'm trying to do.

In SQL, what I would be doing is something like this:

SELECT log.*, COUNT(1) numHits
FROM Application log
GROUP BY Source, Task, Level, Description
ORDER BY numHits DESC
LIMIT 10

Is it possible to do such a thing using xpath?

Edit: Here is a sample Event:


<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>

  <System>
    <Provider Name='MSSQL$SQLEXPRESS' />
    <EventID Qualifiers='16384'>17403</EventID>
    <Level>4</Level>
    <Task>2</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime='2010-10-20T20:06:18.000Z' />
    <EventRecordID>9448</EventRecordID>
    <Channel>Application</Channel>
    <Computer>SHAZTOP</Computer>
    <Security />
  </System>
  <EventData>
    <Data>73094</Data>
    <Binary>
    FB4300000A000000130000005300480041005A0054004F0050005C00530051004C004500580050005200450053005300000000000000</Binary>
  </EventData>
</Event>

like image 363
Skudd Avatar asked Jan 02 '26 07:01

Skudd


2 Answers

XPath 1.0 has four data types: string, number, boolean and node set.

The only XPath ordering criteria is document order (in the given axis direction). That is how you can limit any result node set as @Dimitre and @Welbog have sugested with fn:position().

But, there is no specification that an XPath engine must provide a node set result in any given order. So, you can't sort nor grouping in XPath 1.0. You can select the firsts of each group, but not efficiently. As example:

//Event[not(System/Level = preceding::Level) or 
        not(System/Task = preceding::Task)]

XPath 2.0 has the sequence data type. A sequence has the exclicit order of construction. So, you can group. As example:

for $event (//Event)[index-of(//Event/System/concat(Level,'++',Task),
                              System/concat(Level,'++',Task))[1]]
result //Event[System/Level = $event/System/Level]
              [System/Task = $event/System/Task]

But, because XPath 2.0 has not built-in sorting nor recursion mechanism (you could provide an extension function...) you can't sort.

For that you need a language with built-in sorting or a way to express its algorithm. Both XSLT (1.0 or 2.0) and XQuery have these features.

In SQL, what I would be doing is something like this:

SELECT log.*, COUNT(1) numHits 
FROM Application log 
GROUP BY Source, Task, Level, Description 
ORDER BY numHits DESC 
LIMIT 10

Is it possible to do such a thing using xpath?

In case no sorting is necessary, one can get the first $n nodes selected by any XPath expression by:

(ExpressionSelectingNodeSet)[not(position() > $n)]

where $n can be substituted by a specific number

If there is a requirement that the nodes be sorted on one or more sort-keys, then this is not possible pure XPath, but one can easily perform such tasks with XSLT, using the <xsl:sort> instruction and the XPath position() function:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <nums>
   <xsl:for-each select="num">
    <xsl:sort data-type="number" order="descending"/>
     <xsl:if test="not(position() > 5)">
      <xsl:copy-of select="."/>
     </xsl:if>
   </xsl:for-each>
  </nums>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document:

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>010</num>
</nums>

the correct result, containing only the top 5 numbers is produced:

<nums>
    <num>010</num>
    <num>09</num>
    <num>08</num>
    <num>07</num>
    <num>06</num>
</nums>
like image 30
Dimitre Novatchev Avatar answered Jan 04 '26 12:01

Dimitre Novatchev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!