An XPath Enabled Rule Engine

By Mark Joseph - May 22, 2008 @ 9:05 am

An excellent introduction to Rule Engines can be found at “Chapter1. The Rule Engine” . However, this description is a bit detailed. In general, a rule engine allows the user to define a set of conditional statements (such as “if x then y”), where when the condition (x) is true the result (y) is executed. Both the condition and execution are application specific. Rule engines have been applied to many applications some of which include ad server systems, email filtering, anti-SPAM software, and business management tools. As an example in the advertising space, a typical rule could be: if “mother’s day” then “show image banner A”, where banner A is a gift for mom.

There is a lot of technical jargon used to describe how rule engines work two of which are important to understand the rest of this article. The first term is “stated facts” which are fixed facts that are given as input to the rule evaluation (e.g., the price of a typical car is $22,000). And the second term is “inferred facts” which are facts that are generated by the rule engine (these come from a rule’s actions, e.g., Henry bought an expensive car since it cost more than $22,000).

What follows are details of what makes our rule engine so powerful. While we where designing our rule engine we knew that we need an expression language to define a rule’s conditional logic. Luckily we already had built XPath 2.0 which is a powerful expression language that is embeddable into XML.

Examples of other Rule Engines include open Source Rule Engines in Java (Drools is a great example of this). Another popular rule engine is from ILOG namely JRules and ILOG Rules and how they are used in Business rule management.


Properties of our Rule Engine
1. Our rule engine implements forward chaining where all inferred facts are added to a DOM tree at location under “/P6R:infer/”. The benefit of this is that all inferred facts are accessible via XPath 2.0 expressions.

2. Our XPath 2.0 supports stated facts defined in either XML or JSON , thus our Rule Engine is also JSON enabled.

3. No software programming is required. Our rule engine is controlled by an XML based language we have defined. For example, a basic rule looks like:

<rule name='abc' setname='rover' priority='5'>
   <if test='XPath expression'>
   <then>
      One or more actions (which can also include XPath expressions)
   </then>
</rule>



4. Rules can be added, deleted, modified any time between evaluation calls.

5. The rule engine is easily extensible by any application. This is done via XPath. XPath calls the enclosing application for any function it does not recognize as a predefined XPath function. For example,

<rule name='hotcar' setname='over1'>
   <if test='$g2'/>
   <then>
      <call func="setclickurl( 'www.p6r.com' )" />
      <set-fact name='12345' select="'Hi Henry'" location='/P6R:infer/mealitem' />
   </then>
</rule>

the ’setclickurl’ is not a defined XPath built-in function but is instead defined by the application. Also the variable ‘$g2′ is defined by the application. Our XPath component allows an application to register a special handler object which defines these external functions and variables.

6. Any number of rule sets, rules, and actions in a rule are allowed.

7. Our rule engine has a large set of built-in functionality via a well engineered XML rule language (some of which is presented below and we document in detail in our SDK).

8. Our rule engine has a built-in logging facility. Also XPath 2.0 defines several tracing functions. Both the internal working of the rule engine logic as well as the XPath engine can be traced. For example, XPath 2.0 supports regular expressions. When the XPath log is turned on any regular expression being evaluated is also traced.

9. Rules are compiled so any errors are returned as error codes to the user before the rules are run.

10. Our rule engine is its own object and thus any number of separate rule engine instances can be created for a single or multiple applications. Each instance can be controlled by a different set of rules and can generate a different set of inferred facts.

11. As with all P6R software, our rule engine runs are several platforms which currently include (as of this writting) Windows, Linux, and Solaris.

The following sections are excerpts from our rule engine manual. These small excerpts provide a view into the full expressive power of our engine.


The Rule Engine Language
The basic building block is the rule and it has the following form:

<rule name='abc' setname='rover' priority='5'>
     <if test='XPath expression' >
     <then>
           One or more actions
     </then>
</rule>

Every rule must have an ‘if’ and ‘then’ element. The ‘if’ element defines the conditions when the rule is true and thus can be executed. The ‘then’ element defines one or more actions which are evaluated when a rule is executed.

Rules can be grouped in to rule sets where each set is defined by a unique name. A rule defines which set it belongs do by the use of the optional attribute ’setname’. If no ’setname’ attribute is defined then a rule is placed in the default rule set which is named by ‘#default’. (Note, that the rule set name ‘#default’ is reserved.)

Rules are grouped under a parent element of ‘<rulesets> … </rulesets>’, allowing multiple rules and rule sets to be defined by a single XML document.

Rules can also use the optional attribute of ‘priority’ which defines the relative importance of a rule with all the other rules in the same rule set. If no ‘priority’ attribute is used then a priority of zero (the lowset level) is the default.

In the ‘if’ element, value of the test attribute can be any valid XPath 2.0 expression. These expressions are evaluated against the XML (or JSON) ‘fact’ tree created by a call to the startFacts() API call. This method allows the application to define ’stated’ facts to be used in the evaluation of rules.

When a rules ‘if’ element evaluates to true and it is selected for execution each action defined in its ‘then’ element is executed in order of appearance. There are several possible actions, each is defined in the next section.


The Rule ‘Then’ Element
1) <call func=’XPath Expression’ />
The ‘func’ parameter is required. The func expression should contain a call to a function that is either a built in XPath 2.0 function, or one defined by the calling application via the rule engine setExternalFunctions() method. For example, the XPath expression could be something like “setclick( ‘abc’, $g1 )”, which would be a function defined by the application with two parameters being passed to it. Note, that XPath 2.0 allows any number of parameters to be passed to an application defined function, the parameters to that function must be valid XPath types (e.g., strings, integers, XML node sequences). This action is a good way to call out to application defined functions to execute an external action when a specific condition is satisified (i.e., when the ‘if’ element condition is true).

2) <set-variable name=’$g1′ select=’XPath expression’ />
The ‘name’ and ’select’ parameters are required. This action will first evaluate the XPath expression defined in the select parameter. The result of that expression will be assigned to the global variable designated in the ‘name’ parameter. The rule set that this action is defined in is the rule set used to lookup the global variable (e.g., “rule setname=”example1″ …”, then the ‘example1′ rule set would be used for this action).

3) <set-focus setname=’over’ />
The ’setname’ parameter is required. This action changes the rule set that is currently being evaluated. The change will occur after the current rule is executed. Thus any actions that follow the set-focus action in the same rule will not be affected. If the rule set identified by the setname parameter does not exist then a fatal error will occur and the evaluate() API call will fail and rule execution will stop immediately.

4) <set-fact name=’rover’ select=’XPath expression’ location=’/P6R;infer …’ />
The ‘name’ parameter is required and ’select’ and ‘location’ are optional. This action adds one or more inferred facts onto the inferred fact XML tree under “/P6R:infer”. The value of the ‘name’ parameter defines the XML node to be added so if “name=’rover’” the path to the new inferred fact will be “/P6R:infer/rover”.

However, if the ‘location’ parameter is also defined, for example “location=’/P6R:infer/part1′”, then the new inferred fact will be add at the path “/P6R:infer/part1/rover”, assuming that “part1″ is already in the tree. The ’select’ parameter will evaluate to a valid XPath type value and that will get added to the location in the inferred fact tree. Thus its the value of the select parameter that determines the value of the inferred fact.

The action <set-fact name=’section1′ /> will simply add a new XML node at the path “/P6R:infer/section1″. This is useful for different rule sets to create separate subtrees in the inferred fact tree that is just for that rule set to use. Also the action

“<set-fact name=’paragraph44′ location=’/P6R:infer/section1′ />”,

would create the following nodes in the inferred fact tree “/P6R:infer/section1/paragraph44″. Once this path is created, any number of facts can be “hung off of” any part of that tree (i.e., at the ’section1′ branch or at the ‘paragraph44′ branch).

5) <clear-facts />
This action results in the entire inferred fact tree (i.e., “/P6R:infer”) to be deleted. After this action new inferred facts can be added to a new inferred fact tree. The result of this action is identical to the result of the rule engine API call reset( P6RULE_CLEAR_FACTS ).

6) <delete-fact location=’/P6R:infer …’ />
This action removes all the inferred facts defined in the inferred fact tree located at the path defined by the ‘location’ parameter. After this action, new inferred facts can always be added back onto the tree at the same location that was deleted.

7) <halt />
There are no parameters to this action. This action stops rule engine evaluation immediately. If there are any additional actions that are defined after the ‘halt’ they are ignored. This action results in a successful return of the rule engine’s evaluate() API call (i.e., it does not represent an error condition).


A Simple Example
This example comes directly out of a unit test for our rule engine:

<?xml version='1.0' encoding='ISO-8859-1'?>
<rulesets version='1.0'
   xmlns:P6R='http://www.p6r.com/ruleengine/extensions'>

<variable name='$g1' select='/menu/dessert/item'/>           

-- 'matches' is an XPath 2.0 function implementing Perl Regular Expressions
<rule name='Irvin' prioirty='5'>
   <if test="matches( $g1, '\d\d-\d\d-\d\d', 'i') />
   <then>
     <set-fact name='infer1' select='menu has blueberry tart' />
  </then>
</rule>

<rule name='stoprules'>
<if test='true()'/>
<then>
     <halt/>
</then>
</rule>
</rulesets>

And the stated facts that was input to the above rule set was:
<?xml version='1.0' encoding='UTF-8' ?>
<menu>
   <maincourse>
         <meat>Whole Chiken</meat>
         <soup>green pee</soup>
   </maincourse>
   <dessert id='5'>
       <icecream>chocolate</icecream>
       <item>blueberry 44-34-29 tart</item>
       <item>strawberry 3 layer cake</item>
       <item>vanilla cream pie</item>
   </dessert>
</menu>

Or if your stated facts are in JSON, this input will produce the same result:
 { "menu": {
   "maincourse": {
       "meat": "Whole Chiken",
        "soup": "green pee"
     },
   "dessert": {
        "id": 5,
        "icecream": "chocolate",
        "item": [
             "blueberry 44-34-29 tart",
             "strawberry 3 layer cake",
             "vanilla cream pie"
        ]  } } };

Here are final results when the rules above are evaluated:
<?xml version="1.0" encoding="utf-8" ?>
<P6R:infer xmlns:P6R="http://www.p6r.com/ruleengine">
  <infer1>menu has blueberry tart</infer1>
</P6R:infer>

"An XPath Enabled Rule Engine" was published on May 22nd, 2008 and is listed in Unique Product Features.

Follow comments via the RSS Feed | Leave a comment | Trackback URL

Comments on "An XPath Enabled Rule Engine": 2 Comments

  1. On June 5th, 2008 at 10:26 am Vlad Mangeym said,

    Is it (Rule Engine) something that you have available?
    Is it an open source or commercial product?

    Thanks.

  2. On June 5th, 2008 at 2:51 pm Mark Joseph said,

    Our Rule Engine is a commercial product.
    It is full featured and is “programmed” solely via an XML language and can take fact data either in XML or JSON.
    Please refer to our platform description at:
    http://www.p6r.com/software.html


Leave Your Comment