2010-10-21 47 views
3

我目前正在使用Windows事件日誌的項目。我正在使用wevtutil從事件日誌中獲取結果。我知道wevtutil支持xpath查詢,但由於我是xpath新手,我不知道我可以實現我想要做的事情。使用xpath從wevtutil中選擇前10個事件

在SQL中,我會做的是這樣的:

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

是否有可能使用XPath做這樣的事情?

編輯:下面是一個示例事件:


<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

好問題,+1。查看我的答案,瞭解兩種簡短且完整的XPath和XSLT解決方案。 – 2010-10-21 18:22:34

回答

1

XPath 1.0有四種數據類型:字符串,數字,布爾值和節點集。

唯一的XPath排序標準是文檔順序(在給定的軸方向上)。這就是你可以限制任何結果節點設置爲@Dimitre和@Welbog已經與fn:position()擁塞。

但是,沒有規定XPath引擎必須以任何給定順序提供節點集結果。所以,你不能在XPath 1.0中進行排序和分組。您可以選擇每個組的第一個,但效率不高。例如:

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

XPath 2.0具有序列數據類型。一個序列具有無序的構造順序。所以,你可以分組。作爲例子:

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] 

但是,由於XPath 2.0中沒有內置的排序,也不遞歸機制(你可以提供一個擴展功能......),你不能排序。

爲此,您需要一種內置排序語言或表達算法的方法。 XSLT(1.0或2.0)和XQuery都具有這些功能。

+0

你錯了XPath 2.0。它可以排序。證明:http://www.ximeco.org/Xime/XPathCanSortHlousek.pdf。在XPath 3.0中,它變得簡單而高效。 – 2013-08-29 02:18:12

0

可以使用position()功能來限制你得到的結果:

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

例如,將選擇前十個element元素是根的孩子。

如果你的結構比較複雜,你可以在不同的地方使用position元素。例如,如果element元素可以在多個父存在,但你希望他們的前十位,無論父母的,你可以這樣來做:

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

這種幫助。我將如何做分組?我將編輯原始帖子以分享示例活動。 – Skudd 2010-10-21 18:17:09

+0

XPath沒有內置分組。 – Welbog 2010-10-21 18:19:06

1

在SQL中,我會這樣做是 這樣的:

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

是否有可能使用XPath做這樣的事情 ?

如果不需要進行排序,可以由得到由任何XPath表達式中選擇的第一$n節點:

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

其中$n可以通過特定數量被取代

如果要求節點在一個或多個排序鍵上排序,那麼這是不可能的純XPath,但可以使用XSLT輕鬆執行這些任務,使用<xsl:sort>指令和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> 

當施加於下面的XML文檔這種轉變:

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

正確的結果,僅含有頂部5個號碼產生

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