使用xpath从wevtutil中选择前10个事件

时间:2010-10-21 18:00:58

标签: xpath

我目前正在开发一个使用Windows事件日志的项目。我正在使用wevtutil从事件日志中获取结果。我知道wevtutil支持xpath查询,但由于我是xpath的新手,我不知道我能实现我想要做的事情。

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

3 个答案:

答案 0 :(得分: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,但可以使用<xsl:sort>指令轻松地使用XSLT执行此类任务和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>

答案 1 :(得分: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都具有这些功能。

答案 2 :(得分:0)

您可以使用position()功能来限制您获得的结果:

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

例如,这将选择作为根的子元素的前十个element元素。

如果结构更复杂,可以在不同的地方使用position元素。例如,如果element元素可以存在于多个父元素中,但是您想要前十个元素而不管父元素,则可以这样做:

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