XQuery/Validating a hierarchy

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Whilst schema validation can check for some aspects of model validity, business rules are often more complex than is expressible in XML schema. XQuery is a powerful language for describing more complex rules.

One such rule is that a relationship should define a tree structure,for example, the relationship between an employee and her manager.

Consider the following set of employees:

<company>
  <emp>
      <name>Fred</name>
      <mgr>Bill</mgr>
      </emp>
    <emp>
        <name>Joe</name>
        <mgr>Bill</mgr>
    </emp>
    <emp>
        <name>Alice</name>
        <mgr>Joe</mgr>
    </emp>
    <emp>
        <name>Bill</name>
     </emp>
</company>


The criteria for a valid hierarchy are:

  1. one root (the boss);
  2. every employee has at most one manager;
  3. every employee reports finally to the boss;
  4. there are no cycles

In XQuery we can define the management hierarchy from the boss down to an employee as :

declare function local:management($emp as element(emp) ,
       $hierarchy as element(emp)* ) as element(emp)*  {
     if ($emp = $hierarchy )  (: cycle detected :)
     then ()
     else 
       let $mgr :=  $emp/../emp[name=$emp/mgr]
       return
          if (count($mgr) > 1)  
          then ()  
          else
              if (empty ($mgr))  (: reached the root :)
              then ($emp,$hierarchy)
              else local:management($mgr, ($emp,$hierarchy))
};

The function is initially called as

 local:managment($emp,())

The hierarchy is built up as a parameter to allow cycles to be detected.

Finally, the condition for the management structure to be a tree is

declare function local:management-is-tree($company)) {
    let $boss := $company/emp[empty(mgr)]
    return 
       count($boss) = 1
            and
      (every $emp in $company/emp
          satisfies $boss = local:management($emp,())[1]
      )
};