1

美好的一天,首先感谢您阅读我的 XQuery 问题。

我需要在 XQuery 中实现一个函数来顺序检测数据结构中的项目。由于我是 XQuery 的新手,我仍然发现一些不熟悉的概念,非常感谢那些有多年经验的人提供的帮助,与我在 XQUery/Saxon 的几周相比。

这是日志文件分析的一部分,我已经将相关数据归结为更紧凑的 XML 结构(见下文),该结构按顺序保存在我的 XQuery 模块中。我现在需要将此序列传递给检测数据中特定事件的函数。我的结构如下:-

<SEQUENCE><TIME>0.01</TIME><TAG>2100</TAG><FIELD>PRIMARY_MODE_CMD</FIELD><MODE>MODE1</MODE></SEQUENCE>
<SEQUENCE><TIME>0.57</TIME><TAG>2900</TAG><FIELD>PRIMARY_MODE_CNF</FIELD><MODE>MODE1</MODE></SEQUENCE>
<SEQUENCE><TIME>0.65</TIME><TAG>2900</TAG><FIELD>PRIMARY_MODE_CNF</FIELD><MODE>MODE1</MODE></SEQUENCE>
<SEQUENCE><TIME>1.29</TIME><TAG>2900</TAG><FIELD>PRIMARY_MODE_CNF</FIELD><MODE>MODE1</MODE></SEQUENCE>
<SEQUENCE><TIME>1.94</TIME><TAG>2900</TAG><FIELD>PRIMARY_MODE_CNF</FIELD><MODE>MODE1</MODE></SEQUENCE>
<SEQUENCE><TIME>2.57</TIME><TAG>2900</TAG><FIELD>PRIMARY_MODE_CNF</FIELD><MODE>MODE1</MODE></SEQUENCE>
<SEQUENCE><TIME>3.01</TIME><TAG>3800</TAG><FIELD>JAT_INITIALISE_CMD</FIELD><MODE>UPDATE_JAT_INITIALISE_PARAMS</MODE></SEQUENCE>
<SEQUENCE><TIME>3.03</TIME><TAG>2900</TAG><FIELD>PRIMARY_MODE_CNF</FIELD><MODE>MODE1</MODE></SEQUENCE>
<SEQUENCE><TIME>3.03</TIME><TAG>2900</TAG><FIELD>INVALID_CMD_CNF</FIELD><MODE>INVALID</MODE></SEQUENCE>

XQuery 函数(例如 '*declare function local:analyse_case_1($seq as element() ) as xs:boolean ')必须将整个元素序列(如上)作为参数,如果在其中找到三个事件,则返回“true”严格的顺序,即:

'2100 + PRIMARY_MODE_CMD + MODE1' - followed by:
'2900 + PRIMARY_MODE_CNF + MODE1' - followed by:
'3800 + JAT_INITIALISE_CMD + UPDATE_JAT_INITIALISE_PARAMS' - followed by:
'2900 + INVALID_CMD_CNF + INVALID'

如果发现此订单不正确、缺少项目等,该函数将返回 false。作为第二个要求,如果这些项目之间的时间长于 0.60,它也应该返回 false

在过去一天左右详细研究了 XQuery 之后,我认为这在编译语言中很容易实现,但由于某种原因,我无法立即看到使用 XQuery 的方法。我希望有人能指出我正确的方向吗?

感谢。

4

2 回答 2

1

我的印象是您的要求是查找按顺序但不一定相邻的消息。这可以通过以下形式的查询来实现

exists(
  SEQUENCE[TAG='2100' and FIELD='PRIMARY_MODE_CMD' and MODE='MODE1']
  /following-sibling::SEQUENCE[TAG='2900' and FIELD='PRIMARY_MODE_CNF' and MODE='MODE1']
  /following-sibling::SEQUENCE[TAG='3800' and FIELD='JAT_INITIALISE_CMD' and MODE='UPDATE_JAT_INITIALISE_PARAMS']
  /following-sibling::SEQUENCE[TAG='2900' and FIELD='INVALID_CMD_CNF' and MODE='INVALID'])

问题的第二部分,

it should also return false if the time between these items is longer than 0.60

没有明确规定。你是指第一个和最后一个之间的时间,还是任何一对事件之间的时间?您基本上可以通过将变量绑定到所选元素来处理此问题:

let $x := SEQUENCE[...],
    $y := $x/following-sibling[...],
    $z := $y/following-sibling[...][TIME lt $x/TIME + 0.6]
return exists($z)
于 2012-09-11T11:44:39.780 回答
0

构造for $x at $pos in $seq是你的朋友:

for $x at $pos in $seq
  where $x/TAG eq "2100"
    and $x/FIELD eq "PRIMARY_MODE_CMD"
    and (some $y in subsequence($seq, $pos, count($seq))
           satisfies ($y/TAG eq "2900" and $y/FIELD eq "PRIMARY_MODE_CNF"))
  return $x

这还不是完整的查询,但您应该可以从这里开始。在实践中,我会把它变成几个函数。请注意,subsequence循环内的调用意味着此查询在最坏的情况下需要 O(n²) 时间

于 2012-09-11T08:28:02.527 回答