XQuery/Validating a hierarchy
< XQuery
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:
- one root (the boss);
- every employee has at most one manager;
- every employee reports finally to the boss;
- 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]
)
};