您很有可能要处理包含重复字段的消息,这些字段具有未知数量的重复。示例消息中示例消息里的 Item 字段就是这种情况。
要编写一个考虑到 Item 字段所有实例的过滤器,需要使用可以跨重复字段的所有实例进行迭代的构造。定量谓词允许您对重复字段的所有实例执行谓词,并整理结果。
例如,您可能要验证将订购的这些商品中没有任何一个商品的数量大于 50。要这样做,您可以写:
FOR ALL Body.Invoice.Purchases."Item"[] AS I (I.Quantity <= 50)
使用定量谓词,第一个要注意的就是 FOR ALL 后字段引用末尾处的方括号 []。这些方括号告诉您,您正在遍及 Item 字段的所有实例进行迭代。
在某些情况下,该语法看上去有些多余,因为您可以从上下文获取此信息,但有它可以与其他语法片断保持一致。
AS 子句将名称 I 与重复字段的当前实例关联。这类似于某些面向对象的语言(例如,C++)中使用的迭代器类概念。括号中的表达式是谓词,需要为 Item 字段的每个实例对其进行求值。
这个示例的描述为:
以上是使用 ALL 关键字时如何对谓词求值的描述。替换方法是指定 SOME 或 ANY,它们是等价的。在这种情况下,如果子谓词对于重复字段的任何实例返回 TRUE,则量化谓词返回 TRUE。仅当子谓词对于重复字段的所有实例都返回 FALSE 时,量化谓词才返回 FALSE。如果子谓词返回的是 FALSE 和 UNKNOWN 的混合,则返回的整体值是 UNKNOWN。
在下面的过滤器表达式中:
FOR ANY Body.Invoice.Purchases."Item"[] AS I (I.Title = 'The XML Companion')
子谓词的求值结果是 TRUE。但是,下一个表达式返回 FALSE:
FOR ANY Body.Invoice.Purchases."Item"[] AS I (I.Title = 'C Primer')
因为此发票中不包含 C Primer。如果发票中的某些商品不包含登记标题字段,则子谓词返回 UNKNOWN,定量谓词返回值 UNKNOWN。
FOR ANY Body.Invoice.Purchases."Item"[] AS I (I.Book IS NOT NULL AND I.Book.Title = 'C Primer')
谓词 IS NOT NULL 确保当 Item 字段不包含 Book 时,将从子谓词返回 FALSE 值。
如引用数据库中的列中所述,您还可以通过使用 SELECT 表达式处理消息内字段的任意重复。
您可以使用 [>] 和 [<] 数组下标引用重复字段的第一个和最后一个实例,以及与第一个和最后一个实例相关的实例,即使您不知道有多少实例。这些索引在访问元素的已知的多次出现中描述。
或者,您可以使用 CARDINALITY 函数来确定重复字段有多少个实例。例如:
DECLARE I INTEGER CARDINALITY(Body.Invoice.Purchases."Item"[])