ValidateThis! - Less Verbose XML
Posted At : October 19, 2008 5:16 PM | Posted By : Bob Silverberg
Related Categories: ColdFusion, ValidateThis
I was creating an XML schema definition for my current XML schema and I realized that I could make it much less verbose. I could eliminate most of the "container" elements, such as rules and params and it wouldn't affect its readability or parseability, and would save me some typing when creating the XML files, so I've done that.
For the record, here is the new sample XML file:
2<validateThis xsi:noNamespaceSchemaLocation="validateThis.xsd"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4 <objectProperties>
5 <property name="UserName" desc="Email Address">
6 <rule type="required" contexts="Register,Update" />
7 <rule type="email" contexts="Register,Update"
8 failureMessage="Hey, buddy, you call that an Email Address?" />
9 </property>
10 <property name="Nickname">
11 <rule type="custom" contexts="Register,Update">
12 <param methodname="CheckDupNickname" />
13 </rule>
14 </property>
15 <property name="UserPass" desc="Password">
16 <rule type="required" contexts="Register,Update" />
17 <rule type="rangelength" contexts="Register,Update">
18 <param minlength="5" />
19 <param maxlength="10" />
20 </rule>
21 <rule type="equalTo" contexts="Register,Update">
22 <param ComparePropertyName="VerifyPassword" />
23 </rule>
24 </property>
25 <property name="VerifyPassword" desc="Verify Password">
26 <rule type="required" contexts="Register,Update" />
27 </property>
28 <property name="FirstName" desc="First Name">
29 <rule type="required" contexts="Update" />
30 </property>
31 <property name="LastName" desc="Last Name">
32 <rule type="required" contexts="Update" />
33 <rule type="required" contexts="Register">
34 <param DependentPropertyName="FirstName" />
35 </rule>
36 </property>
37 <property name="LikeOther" desc="What do you like?">
38 <rule type="required" contexts="Register,Update"
39 failureMessage="If you don't like Cheese and you don't like Chocolate, you must like something!">
40 <param ServerCondition="getLikeCheese() EQ 0 AND getLikeChocolate() EQ 0" />
41 <param ClientCondition="$("[name='LikeCheese']").getValue() == 0 && $("[name='LikeChocolate']").getValue() == 0;" />
42 </rule>
43 </property>
44 <property name="HowMuch" desc="How much money would you like?">
45 <rule type="numeric" contexts="Register,Update" />
46 </property>
47 <property name="AllowCommunication" desc="Allow Communication" />
48 <property name="CommunicationMethod" desc="Communication Method">
49 <rule type="required" contexts="Register,Update"
50 failureMessage="If you are allowing communication, you must choose a communication method.">
51 <param DependentPropertyName="AllowCommunication" />
52 <param DependentPropertyValue="1" />
53 </rule>
54 </property>
55 </objectProperties>
56</validateThis>
And here's the xsd, without the annotations that I've since added to it:
2 <xs:element name="validateThis">
3 <xs:complexType>
4 <xs:sequence>
5 <xs:element name="objectProperties">
6 <xs:complexType>
7 <xs:sequence>
8 <xs:element
9 maxOccurs="unbounded"
10 name="property">
11 <xs:complexType>
12 <xs:sequence>
13 <xs:element
14 minOccurs="0"
15 maxOccurs="unbounded"
16 name="rule">
17 <xs:complexType>
18 <xs:sequence>
19 <xs:element
20 minOccurs="0"
21 maxOccurs="unbounded"
22 name="param">
23 <xs:complexType>
24 <xs:anyAttribute
25 namespace="##any"
26 processContents="lax"/>
27 </xs:complexType>
28 </xs:element>
29 </xs:sequence>
30 <xs:attribute
31 name="type"
32 type="xs:string"
33 use="required"/>
34 <xs:attribute
35 name="contexts"
36 type="xs:string"
37 use="optional"/>
38 <xs:attribute
39 name="failureMessage"
40 type="xs:string"
41 use="optional"/>
42 </xs:complexType>
43 </xs:element>
44 </xs:sequence>
45 <xs:attribute
46 name="name"
47 type="xs:string"
48 use="required"/>
49 <xs:attribute
50 name="desc"
51 type="xs:string"
52 use="optional"/>
53 </xs:complexType>
54 </xs:element>
55 </xs:sequence>
56 </xs:complexType>
57 </xs:element>
58 </xs:sequence>
59 </xs:complexType>
60 </xs:element>
61</xs:schema>
That way, when you are using your favourite XML editor, you shoud get inline help on exactly what each element and attribute does.
You can see examples of this in the Transfer XSD's.
http://www.transfer-orm.com/transfer/resources/xsd...
How did I know to add them, you might ask? By looking at transfer.xsd, of course! It was an excellent reference to use while creating my own schema.
I've been enjoying your Transfer and Validation posts a lot, thanks for blogging on these topics.
I really like where you're going with your validation system, it definitely matches my mental model for how to develop a flexible validation solution. Have you thought about implementing validation-inheritance or declaratively binding a form submission to a validation definition (to promote DRY principles)? I'd be interested in hearing your thoughts on some of these "features". I have described these features with some sample markup on Ben Nadel's blog during another validation discussion. If you read my comment, what I said above will probably make more sense :)
http://www.bennadel.com/blog/1034-Exercise-List-Th...
Thanks again for sharing your thoughts and techniques with all of us!
I just read through that post and your comments. It's the first time I've read it and it's amazing how similar our requirements are ;-) Regarding the two "features" that you mention:
I understand what you're getting at with the validation inheritance scenario. There is nothing "baked in" right now that would implement that, but it wouldn't be that difficult to add. I see that as a bit of an edge case currently, so I don't think I'll add it before releasing the code, but if turns out that people are interested in using the code, and it's a feature people want, I'll consider adding it.
Regarding the formValidations thing, I believe that this requirement is met by the context attribute. I realize that I didn't cover that in any great detail, but basically it allows you to define the context in which the rule should apply to the business object. You can, if you wish, equate context with form, and I think it would give you what you want.
Have I addressed your questions?