Q. Can I use schema to validate data fields that depend on other fields?Hi all, I'm an XML newbie, and despite looking in several XML books, I haven't been able to find out if it's possible to do what I need to do using XML. I have been looking at trying to do the job using schema. Here's the situation: Say I have the following fields: 1. Name (driver's name) 2. Vehicle_Brand (valid values: Chevrolet, BMW, Cadillac. This field cannot be valued if field #4 is valued.) 3. Vehicle_Model (valid values: Monte Carlo or Cavalier if #2 is Chevrolet; 325, 540, 740 if #2 is BMW; Catera, Escalade, Eldorado, or Seville if #2 is Cadillac. This field is required if #2 is populated. Otherwise, it must be NULL if #2 is null.) 4. Bicycle_Brand (valid values: Schwinn, Trek. Field cannot be valued if #2 is valued.) How can I use XML to create a validation scenario that will fit my situation? A [flax]. Henrik Motakef I’m not sure what you mean by “fields”. If they are fields in a Database schema, and you are free in how the exact XML representation looks like, you could desing it so that it works more or less flawlessly with W3C XML Schema. For example, you could make your XML look like this: <foo> <driver-name>...</driver-name> <vehicle> <chevrolet model="Monte Carlo"/> </vehicle> </foo> <foo> <driver-name>...</driver-name> <bicycle brand="Schwinn"/> </foo> A schema for this could look like this: <xs:element name="foo"> <xs:complexType> <xs:sequence> <!-- The driver's name can always appear --> <xs:element name="driver-name" type="xsd:string"/> <!-- There may be either of "vehicle" or "bicycle", --> <!-- but not both, because field #2 and #4 are --> <!-- mutually exclusive --> <xs:choice> <!-- A bicycle has a brand, but is not further --> <!-- structured --> <xs:element name="bicycle"> <xs:complexType> <xs:attribute name="brand"> <xs:simpleType> <xs:restriction base="xs:token"> <xs:enumeration value="Schwinn"/> <xs:enumeration value="Trek"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> <!-- Vehicles are subdivided in brands that are --> <!-- themselves subdivided in models, so they --> <!-- need a bit more structure. --> <xs:element name="vehicle"> <xs:complexType> <xs:choice> <xs:element name="chevrolet"> <xs:complexType> <xs:attribute name="model"> <xs:simpleType> <xs:restriction base="xs:token"> <xs:enumeration value="Monte Carlo"/> <xs:enumeration value="Cavalier"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> <xs:element name="bmw"> <xs:complexType> <xs:attribute name="model"> <xs:simpleType> <xs:restriction base="xs:token"> <xs:enumeration value="325"/> <xs:enumeration value="540"/> <xs:enumeration value="740"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> <!-- Same for cadillac --> </xs:choice> </xs:complexType> </xs:element> <!-- end of "vehicle" --> </xs:choice> </xs:sequence> </xs:complexType> </xs:element> (Beware: I don’t have any schema tool at hand right now, so the actual syntax might be utter rubbish. I hope you get the point nevertheless) However, if you need your XML to be flat, i.e. like <foo> <driver-name>...</driver-name> <vehicle-brand>...</vehicle-brand> <vehicle-model>...</vehicle-model> </foo> <foo> <driver-name>...</driver-name> <bicycle-brand>...</bicycle-brand> </foo> you will have some problems expressing your constraints with W3C XML Schema. In that case, IMHO the best way to proceed is to write a schema that doesn’t validate all these constraints, and use a schema language that is better suited for this task in addition. Schematron seems to be best suited for this kind of requirements; it is based on asserting arbitrary XPath expressions, and can even be embedded in W3C XML Schema, see http://www.ascc.net/xml/resource/schematron/schematron.html. If you don’t want to mix schema languages (and expressing all of this schema in Schematron would become awkward), you could use RELAX NG, which unlike W3C XML Schema doesn’t disallow `non-deterministic’ types, so it would be possible to define different types for the different kinds of vehicles/bicycles even if some of their content overlaps. For example, in compact syntax:
start = foo
foo = element foo { driver-name, (vehicle | bicycle) }
driver-name = element driver-name { text }
bicycle = element bicycle-brand { "Schwinn" | "Trek" }
vehicle = chevrolet | bmw | cadillac
chevrolet = element vehicle-brand { "Chevrolet" },
element vehicle-model { "Monte Carlo" | "Cavalier" }
bmw = element vehicle-brand { "BMW" },
element vehicle-model { "325" | "540" | "740" }
cadillac = element vehicle-brand { "Cadillac" },
element vehicle-model {
"Catera"
| "Escalade"
| "Eldorado"
| "Seville"
}
|
| Нас поддерживают:
© Vasil I. Yaroshevich, 2001-2005 Driven by DokuWiki © 2004-2005 Andreas Gohr |