In the last article, we grouped assertions into rules. As you know, each rule has its own context that it acts upon. So, grouping assertions into a rule provides a way to organize assertions that apply to the same elements. In this article, we'll start by explaining patterns, which takes organization to a new level.
Schematron Patterns and Validation - Abstract Patterns (Page 2 of 4 )
Abstract patterns also exist in Schematron. They are similar to abstract rules in that they must be extended in some way by other patterns, but they are more complex and powerful, and they solve a different problem. Sometimes, two XML structures convey the same information, but they are structured differently. Abstract patterns allow a way to operate on both structures in the same way.
Say, for example, that we're representing an e-mail and a Windows Live instant message in XML. The markup for the two might look something like this:
<email> <header> <to>email@example.com</to> <from>firstname.lastname@example.org</from> </header> <body> Hello. How are you? </body> </email> <live_message> <to>email@example.com</to> <from>firstname.lastname@example.org</from> <message> Hello. How are you? </message> </live_message>
The same information is conveyed in both structures: a sender, a recipient, and a message. The same constraints, then, could apply to both structures. For example, we could make sure that the elements representing the information do indeed exist. However, the elements representing these fields are at different paths in each structure and may have different names. Based on this, it might seem that we'd have to create two patterns that are essentially duplicates of each other just to accommodate the different paths and element names.
However, abstract patterns provide a much easier and shorter way to do this. We can create an abstract pattern that deals with everything in an abstract matter. Using an abstract pattern, we can, for example, create the markup that checks for a sender without knowing exactly how the sender is represented. Then, another pattern could extend this and pass the exact location of the sender element as a parameter. The abstract parameter would reference the values of these parameters in order to set constraints.
Let's see how all of this would look. If we wanted to verify that each message has a sender, a recipient, and a message, then we're checking for the presence of three elements. This requires one rule and three assertions. The rule context expression and the test expression simply point to the location of the relevant elements. Since we don't know the exact paths, though, we can use parameter references. Let's create the abstract pattern for all of this, using parameter references for what we don't know. To create an abstract pattern, the abstract attribute of the pattern element needs to be set to “true,” and the pattern needs to be given a unique identifier using the id attribute. Here's what the abstract pattern looks like:
<patternid="message_structure"abstract="true"> <rulecontext="$message"> <asserttest="$sender"> A message has a sender. </assert> <asserttest="$recipient"> A message has a recipient. </assert> <asserttest="$body"> A message has a body. </assert> </rule> </pattern>
As you can see, the abstract pattern looks just like a normal pattern, except the rule context expression and the test expressions are just references to the parameters. Other patterns can pass the necessary values as parameters. They simply need to have is-a attributes that point to the abstract pattern. Here are the two patterns to test the structure of an e-mail and a Windows Live message:
Now, the XML structure representing an e-mail and the XML structure representing a Windows Live message will both be checked for a sender, a recipient, and a body, even though these three pieces of information are represented differently.