2010-10-21 5 views
3

Je travaille actuellement sur un projet qui utilise le journal des événements Windows. J'utilise wevtutil pour obtenir les résultats des journaux d'événements. Je sais que wevtutil prend en charge les requêtes xpath, mais comme je ne connais pas xpath, je ne sais pas si je peux réaliser ce que j'essaie de faire.Sélectionnez les 10 meilleurs événements de wevtutil en utilisant xpath

Dans SQL, ce que je ferais est quelque chose comme ceci:

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

Est-il possible de faire une telle chose en utilisant XPath?

Edit: Voici un exemple de l'événement:


<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> 

+0

Bonne question, +1. Voir ma réponse pour deux solutions XPath et XSLT complètes et courtes. –

Répondre

1

XPath 1.0 possède quatre types de données: chaîne, nombre, booléen et ensemble de nœuds.

Le seul critère de commande XPath est l'ordre des documents (dans la direction de l'axe donnée). C'est ainsi que vous pouvez limiter n'importe quel jeu de nœuds de résultat lorsque @Dimitre et @Welbog ont été associés à fn:position(). Mais, il n'y a pas de spécification qu'un moteur XPath doit fournir un résultat d'ensemble de nœuds dans un ordre donné. Donc, vous ne pouvez pas trier ni regrouper dans XPath 1.0. Vous pouvez sélectionner les premières de chaque groupe, mais pas efficacement. Par exemple:

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

XPath 2.0 a le type de données de séquence. Une séquence a l'ordre de construction exclusif. Donc, vous pouvez grouper. A titre d'exemple:

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] 

Mais, parce que XPath 2.0 n'a pas de tri intégré ni mécanisme de récursivité (vous pouvez fournir une fonction d'extension ...) vous ne pouvez pas trier.

Pour cela vous avez besoin d'une langue avec un tri intégré ou un moyen d'exprimer son algorithme. Les deux XSLT (1.0 ou 2.0) et XQuery ont ces caractéristiques.

+0

Vous avez tort à propos de XPath 2.0. Il peut trier. Preuve: http://www.ximeco.org/Xime/XPathCanSortHlousek.pdf. Dans XPath 3.0, cela devient simple et efficace. –

0

Vous pouvez utiliser la fonction position() pour limiter les résultats que vous obtenez:

/root/element[position()<=10] 

Par exemple, que choisirait la dix premiers éléments element qui sont des enfants de la racine.

Si votre structure est plus compliquée, vous pouvez utiliser l'élément de position à différents endroits. Par exemple, si l'élément element peut exister dans plus d'un parent, mais vous voulez les dix premiers d'entre eux quel que soit parent, vous pouvez le faire de cette façon: ce

(/root/parent1/element | /root/parent2/element)[position()<=10] 
+0

Ce genre de aide. Comment ferais-je le regroupement si? Je vais modifier le post d'origine pour partager un exemple d'événement. – Skudd

+0

XPath n'a pas de regroupement intégré. – Welbog

1

Dans SQL, je serais faire est quelque chose comme ceci:

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

est-il possible de faire une telle chose en utilisant XPath?

Dans le cas où aucun tri est nécessaire, on peut obtenir les premiers $n noeuds sélectionnés par une expression XPath par:

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

$n peut être substitué par un numéro spécifique

S'il y a une exigence que les noeuds soient triés sur une ou plusieurs clés de tri, alors ce n'est pas possible XPath pur, mais on peut facilement effectuer de telles tâches avec XSLT, en utilisant leinstructionet la fonction XPath position():

<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> 

Lorsque cette transformation est appliquée sur le document XML suivant:

<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> 

le résultat correct, ne contenant que les 5 premiers numéros est produit :

<nums> 
    <num>010</num> 
    <num>09</num> 
    <num>08</num> 
    <num>07</num> 
    <num>06</num> 
</nums> 
Questions connexes