Let's start with a type of XML document. Each XML file will define a person. It looks like this, person.xml:
<person age="17" gender="male"> <name> <first>Peter</first> <last>Scott</last> </name> <tagline>Hey, Steve!</tagline> </person>
In plain English, a person has age and gender attributes, a name tag (containing first and last fields each containing some alphabetic text with no spaces), and a tagline tag containing that person's favorite thing to say. Let's write a matcher for that:
(use-package :xml-psychiatrist) (use-package :xmls-utilities) (toplevel-match (tag "person" ((attr "age" :type '(integer 0 170)) (attr "gender" :possible-values '("male" "female"))) (tag "name" () (tag "first" () (pcdata :matches-regexp "^[a-zA-Z]+$")) (tag "last" () (pcdata :matches-regexp "^[a-zA-Z]+$"))) (tag? "tagline" () (pcdata))) (parse-xml-file "person.xml"))
Look that over until you understand it. You can look up all the little bits; this is an example of how you put them together. Try messing up person.xml and seeing what happens. To get you started, let's try making a very old person:
<person age="65000000" gender="male"> <name> <first>Peter</first> <last>Scott</last> </name> <tagline>Hey, Steve!</tagline> </person>
When we validate this, it should choke when it sees the claim that this person is 65 million years old. Let's try running our validation code again:
NIL "In \"person\" tag, the attribute \"age\" is not allowed here."
Sure enough, the validator caught the mistake. It's a bit on the stupid side, so it says that the attribute age is not allowed there rather than that the attribute age is way too big, but at least you get some idea of where the problem is.