我目前正在开发一个使用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>
答案 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]