Match and Except Expression
A mapping rule has a match expression that specifies which elements from the input XML document stream may trigger its activation. The except expression has precisely the same syntax as the match expression, but serves to limit which elements trigger the mapping rule activation. The match expression has the mechanism to identify a desired element based on the element’s:
- name
- ancestors, and/or
- attribute names and/or values.
The match expression is represented, in xfMap, by the <mapping> element’s match attribute. The syntax for the match expression’s value is:
(/)(ancestorElement/)*element({index})?([booleanExpr])?
Where element specifies the QName of an element E in the input document stream. E is called the match QName.
Note: Note: Since element specifies a QName the prefix for the QName must be bound to a particular URI. All XML Namespace declarations in an xfMap must appear at the root of the xfMap document, i.e., in the <xfMap> element.
But if the prefix is found not to have a corresponding XML Namespace declaration, then the prefix will be ignored in comparisons, i.e., only the local-name of the element becomes significant. This is to keep backward compatibility with existing xfMaps written before supporting XML Namespaces.
The match QName may be optionally prefixed by the QName of its ancestor elements ancestorElement with each ancestor QName separated by the forward slash (/). This prefix is called the match ancestors. Using the forward slash (/) in the beginning of the match expression will cause the expression to match while anchored at the root.
The match QName may be followed by an index, a positive number, that is enclosed within ‘{‘ and ‘}’. The number enclosed within the curly braces is called the match index. The match index it indicates, not the position, but the count of that particular element, in the context of its parent.
The match QName may be suffixed by a Boolean expression, booleanExpr, that evaluates on E’s attributes. When present, the Boolean expression must be enclosed in square brackets []. This suffix is called the match condition.
The following illustrates the grammar of the match condition:
booleanExpr = attrCondition |andExpr |orExpr |‘(‘ booleanExpr ‘)’ andExpr = booleanExpr ‘and’ booleanExpr orExpr = booleanExpr ‘or’ booleanExpr attrCondition =‘@’attrName(’+’|’-’) |‘@’attrName(‘=’|’!=’)(‘"’|"’")attrValue(‘"’|"’")
Note: Note: The XML Reader evaluates the Boolean expression in a right associative way. For complex Boolean expressions, the use of parentheses is recommended to indicate the intended precedence of evaluation.
The match condition is a Boolean expression booleanExpr. A Boolean expression may be a single attribute condition attrCondition, or it may be a sequence of parenthesized logically connected attributes conditions. The value of the match condition then depends on the individual attribute conditions in the Boolean expression.
From the grammar above, an attribute condition production attrCondition may be specified in four different ways; assume that E is the element referred to by the match QName and match ancestors then:
- @attrName+ evaluates to true if E contains an attribute with the name attrName, else the production evaluates to false.
- @attrName- evaluates to true if E does not contain an attribute with the name attrName, else the production evaluates to false.
- @attrName = ’attrValue’ evaluates to true if E contains an attribute with the name attrName and the value attrValue, else the production evaluates to false.
- @attrName != ‘attrValue’ evaluates to true if E contains an attribute with the name attrName and the value of that attribute does not equal attrValue; else the production evaluates to false.
Note: If the enclosing quote of the whole match expression value was a single quotation mark, then the attrValue in c) and d) should be enclosed in double quotation marks.
We are now ready to state the conditions for which an element in the input XML document may trigger the activation of a mapping rule.
A mapping rule M matches an element E when all of the following three conditions are satisfied:
- if M’s match QName equals E’s element QName; and
- if M contains an optional match index i, then E must be the ith child type refer to in 1) in the context of its parent.
- if M contains the optional match ancestors prefix, then E’s ancestors must equal, in the same order, as the ones listed in the prefix; and
- if M contains the optional match condition suffix, then the suffix must evaluate to true according to the E’s attributes.
- if M’s except expression does not match under the previous three rules.
Note: 2, 3 and 4 are also satisfied when the match expression does not contain a match index, match ancestors prefix or a match condition suffix, respectively.
Using wildcards: In addition, each QName either in the match QName or in the match ancestors may be substituted by a wildcard, *, that matches any QName. The wildcard can also be specified either in the prefix and/or the local-name of a QName: *:local-name, or prefix:*, or *:* (which is the same as a single *).
When a match expression M matches an element E in the input XML document stream, we also say that the mapping rule R containing M matches E. That is, R matches E.
Consider, for example, the following input XML document fragment:
<player gender="female" name="Laura" id="3453" position="defense"> <coach> <id>1234</id> </coach> <coach> <id>5678</id> </coach> <manager> <id>7889</id> </manager> </player> <player gender="male" name="Juan" id="1234" position="forward"> <coach> <id>1234</id> </coach> <coach> <id>5678</id> </coach> <manager> <id>7889</id> </manager> </player> <player gender="male" name="Lucas" id="1234"> <coach> <id>1234</id> </coach> <coach> <id>5678</id> </coach> <manager> <id>7889</id> </manager> </player>
The following mapping rules matches various elements from the above XML document fragment:
<mapping match="player"> <!-- matches all player elements --> </mapping> <mapping match="player{3}"> <!-- matches the 3rd player element --> </mapping> <mapping match="coach/id"> <!-- matches all id elements having a parent coach element --> </mapping> <mapping match="coach{2}/id"> <!-- matches the id for the second child coach of a player --> </mapping> <mapping match="manager/id"> <!-- matches all id elements having a manager parent --> </mapping> <mapping match="manager{1}/id"> <!-- matches the first manager’s id in a player element, note that we don’t set the match index to 3 since the index does not specify the position (manager is the 3rd child of every player). -> </mapping> <mapping match="player[@gender=’female’ or @position=’forward’"> <!-- matches all player elements that are female in gender playing a forward position --> </mapping> <mapping match="player[@position-]"> <!-- matches all player elements containing no position attribute --> </mapping> <mapping match="player[@gender=’male’ and @position=’backward’ and @name!=’Juan’]"> <!-- matches all players that are male, playing a backward position and are not named Juan --> </mapping> <mapping match="player/*"> <!-- matches any element having a player element as its parent --> </mapping> <mapping match="player/*{2}"> <!-- matches the second element having a player element as its parent --> </mapping>
<mapping match="/*"> <!-- matches the root element and only the root element --> </mapping>