Jump to content

Choice not working as expected?


craigewens

Recommended Posts

Hi all,Here is my XML file:

<SCAMA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SCAMA - Schema2.xsd">	<USERS size="4">		<USER>last_first1</USER>		<USER>last_first2</USER>		<USER>last_first3</USER>		<USER>last_first4</USER>	</USERS>	<GROUPS size="1">		<GROUP id="group1">			<PORTS size="2">				<PORT id="port1" size="2">					<SOURCE_FILES size="4">						<FILE>c:\group1\port1\source_file1.txt</FILE>						<FILE>c:\group1\port1\source_file2.txt</FILE>						<FILE>c:\group1\port1\source_file3.txt</FILE>						<FILE>c:\group1\port1\source_file4.txt</FILE>					</SOURCE_FILES>					<START_FREQ>12000000000</START_FREQ>					<STOP_FREQ>12000000000</STOP_FREQ>					<POINTS>801</POINTS>					<DESTINATION>c:\group1\port1\dest_file1.txt</DESTINATION>				</PORT>				<PORT id="port2" size="2">					<SOURCE_FILES size="2">						<FILE>c:\group2\port2\source_file1.txt</FILE>						<FILE>c:\group2\port2\source_file2.txt</FILE>					</SOURCE_FILES>					<FREQ_MASTER>c:\group2\port2\freq_master.txt</FREQ_MASTER>					<DESTINATION>c:\group2\port2\dest_file1.txt</DESTINATION>				</PORT>			</PORTS>		</GROUP>	</GROUPS></SCAMA>

and here is my schema:

<?xml version="1.0" encoding="UTF-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">	<xs:element name="SCAMA">		<xs:complexType>			<xs:sequence>				<xs:element ref="USERS"/>				<xs:element ref="GROUPS"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="USERS">		<xs:complexType>			<xs:sequence>				<xs:element name="USER" type="NonBlankString" maxOccurs="unbounded"/>			</xs:sequence>			<xs:attribute name="size" type="NonBlankString" use="required"/>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="GROUPS">		<xs:complexType>			<xs:sequence>				<xs:element ref="GROUP"/>			</xs:sequence>			<xs:attribute name="size" type="xs:byte" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="GROUP">		<xs:complexType>			<xs:sequence>				<xs:element ref="PORTS"/>			</xs:sequence>			<xs:attribute name="id" type="xs:string" use="required"/>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="PORTS">		<xs:complexType>			<xs:sequence>				<xs:element ref="PORT" maxOccurs="unbounded"/>			</xs:sequence>			<xs:attribute name="size" type="xs:byte" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="PORT">		<xs:complexType>			<xs:sequence>				<xs:element ref="SOURCE_FILES"/>				<xs:choice>					<xs:element ref="DEFINED_FREQS"/>					<xs:element name="FREQ_MASTER" type="xs:string"/>				</xs:choice>				<xs:element name="DESTINATION" type="NonBlankString"/>			</xs:sequence>			<xs:attribute name="id" type="NonBlankString" use="required"/>			<xs:attribute name="size" type="NonBlankString" use="required"/>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="DEFINED_FREQS">		<xs:complexType>			<xs:sequence>				<xs:element ref="START_FREQ"/>				<xs:element ref="STOP_FREQ"/>				<xs:element name="POINTS" type="xs:short"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<xs:element name="START_FREQ">		<xs:complexType>			<xs:attribute name="units" type="UnitsEnumType" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="STOP_FREQ">		<xs:complexType>			<xs:attribute name="units" type="UnitsEnumType" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="SOURCE_FILES">		<xs:complexType>			<xs:sequence>				<xs:element name="FILE" type="NonBlankString" maxOccurs="unbounded"/>			</xs:sequence>			<xs:attribute name="size" type="NonBlankString" use="required"/>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:simpleType name="UnitsEnumType">		<xs:annotation>			<xs:documentation>This is the enumeration of all the different type of Units</xs:documentation>		</xs:annotation>		<xs:restriction base="xs:string">			<xs:enumeration value="Hz"/>			<xs:enumeration value="kHz"/>			<xs:enumeration value="MHz"/>			<xs:enumeration value="GHz"/>		</xs:restriction>	</xs:simpleType>	<xs:simpleType name="NonBlankString">		<xs:restriction base="xs:string">			<xs:minLength value="1"/>			<xs:whiteSpace value="collapse"/>		</xs:restriction>	</xs:simpleType></xs:schema>

The problem is that the choice aspect is not working correctly.Within the PORT element i would like to either have a FREQ_MASTER element or START_FREQ, STOP_FREQ and POINTS elements.Is it possible the way i'm trying to do this?I keep getting the error "Unexpected child element 'START_FREQ'.Please can some experts assist?Much thanksCraig.

Link to comment
Share on other sites

Well, I believe this is how it should be, scince you want one of them, not all of them. I mean, your XML has:

<START_FREQ>12000000000</START_FREQ><STOP_FREQ>12000000000</STOP_FREQ>

When only one of them can exist. And btw, your XML also has other validation errors according to the schema. "units" for example is a required attribute. Also, in order to allow the actual entering of numbers inside those two elements, add mixed="true" to the complexType definition.

Link to comment
Share on other sites

Thank you for your reply... i am using XML Spy to validate the XML and it didn't get as far as stating that i forgot the units part :) With regards to the choice section i believe we are misunderstanding what i wish to achieve.I wold like the port node to contain either a single element called <FREQ_MASTER> or three elements called <START_FREQ>, <STOP_FREQ> and <POINTS>.So the XML file i showed above has two different contents for PORT, of which both should be valid... i just can't get the schema to adhere to my desires.With regards to your comment about the

mixed="true"
, can you expand upon which elements would require this?Thank you once again for taking the time to assist.Craig.
Link to comment
Share on other sites

I'm not even sure you can define that with Schema 1.0. What you can do, and have almost done however is to select either FREQ_MASTER or a single other element (DEFINED_FREQS) to hold the other three.The mixed="true" attribute should be added as an attirbute to a complex type definition of an element that can contain anything else, other then text. Scince your START_FREQ contains both text AND an attribute "unit", it must be mixed="true" in it's definition like so:

<xs:element name="START_FREQ"><xs:complexType mixed="true">

Link to comment
Share on other sites

Once again, thank you for your help.I have heeded your comments and updated my xsd and xml file accordingly.XML

<SCAMA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SCAMA - Schema2.xsd">	<USERS size="4">		<USER>name1</USER>		<USER>name2</USER>		<USER>name3</USER>		<USER>name4</USER>	</USERS>	<GROUPS size="1">		<GROUP id="group1">			<PORTS size="2">				<PORT id="port1" size="2">					<SOURCE_FILES size="4">						<FILE>c:\group1\port1\source_file1.txt</FILE>						<FILE>c:\group1\port1\source_file2.txt</FILE>						<FILE>c:\group1\port1\source_file3.txt</FILE>						<FILE>c:\group1\port1\source_file4.txt</FILE>					</SOURCE_FILES>					<DEFINED_FREQS>						<START_FREQ units="Hz">12000000000</START_FREQ>						<STOP_FREQ units="Hz">12000000000</STOP_FREQ>						<POINTS>801</POINTS>					</DEFINED_FREQS>					<DESTINATION>c:\group1\port1\dest_file1.txt</DESTINATION>				</PORT>				<PORT id="port2" size="2">					<SOURCE_FILES size="2">						<FILE>c:\group2\port2\source_file1.txt</FILE>						<FILE>c:\group2\port2\source_file2.txt</FILE>					</SOURCE_FILES>					<FREQ_MASTER>c:\group2\port2\freq_master.txt</FREQ_MASTER>					<DESTINATION>c:\group2\port2\dest_file1.txt</DESTINATION>				</PORT>			</PORTS>		</GROUP>	</GROUPS></SCAMA>

XSD

<?xml version="1.0" encoding="UTF-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">	<xs:element name="SCAMA">		<xs:complexType>			<xs:sequence>				<xs:element ref="USERS"/>				<xs:element ref="GROUPS"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="USERS">		<xs:complexType mixed="true">			<xs:sequence>				<xs:element name="USER" type="NonBlankString" maxOccurs="unbounded"/>			</xs:sequence>			<xs:attribute name="size" type="NonBlankString" use="required"/>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="GROUPS">		<xs:complexType mixed="true">			<xs:sequence>				<xs:element ref="GROUP"/>			</xs:sequence>			<xs:attribute name="size" type="xs:byte" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="GROUP">		<xs:complexType mixed="true">			<xs:sequence>				<xs:element ref="PORTS"/>			</xs:sequence>			<xs:attribute name="id" type="xs:string" use="required"/>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="PORTS">		<xs:complexType mixed="true">			<xs:sequence>				<xs:element ref="PORT" maxOccurs="unbounded"/>			</xs:sequence>			<xs:attribute name="size" type="xs:byte" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="PORT">		<xs:complexType mixed="true">			<xs:sequence>				<xs:element ref="SOURCE_FILES"/>				<xs:choice>					<xs:element ref="DEFINED_FREQS"/>					<xs:element name="FREQ_MASTER" type="xs:string"/>				</xs:choice>				<xs:element name="DESTINATION" type="NonBlankString"/>			</xs:sequence>			<xs:attribute name="id" type="NonBlankString" use="required"/>			<xs:attribute name="size" type="NonBlankString" use="required"/>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="DEFINED_FREQS">		<xs:complexType>			<xs:sequence>				<xs:element ref="START_FREQ"/>				<xs:element ref="STOP_FREQ"/>				<xs:element name="POINTS" type="xs:short"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<xs:element name="START_FREQ">		<xs:complexType mixed="true">			<xs:attribute name="units" type="UnitsEnumType" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="STOP_FREQ">		<xs:complexType mixed="true">			<xs:attribute name="units" type="UnitsEnumType" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="SOURCE_FILES">		<xs:complexType mixed="true">			<xs:sequence>				<xs:element name="FILE" type="NonBlankString" maxOccurs="unbounded"/>			</xs:sequence>			<xs:attribute name="size" type="NonBlankString" use="required"/>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:simpleType name="UnitsEnumType">		<xs:annotation>			<xs:documentation>This is the enumeration of all the different type of Units</xs:documentation>		</xs:annotation>		<xs:restriction base="xs:string">			<xs:enumeration value="Hz"/>			<xs:enumeration value="kHz"/>			<xs:enumeration value="MHz"/>			<xs:enumeration value="GHz"/>		</xs:restriction>	</xs:simpleType>	<xs:simpleType name="NonBlankString">		<xs:restriction base="xs:string">			<xs:minLength value="1"/>			<xs:whiteSpace value="collapse"/>		</xs:restriction>	</xs:simpleType></xs:schema>

These two files now validate through XMLSpy which I presume is a good sign.Can you see any other issues with my XML? It's the first time I've had to define anything like this myself and it's going to be used as an input to an application I'm writing so i'd like to use best practices from the start.Craig.

Link to comment
Share on other sites

Well, the only major thing I've noticed is that you're defining some of your attributes twice. As far as I know, attributes could be referenced with the ref attribute just as elements, so that you don't need to define them more then once.GROUP I believe shoudn't be "mixed" as it doesn't have any text nodes, but only elements and attributes inside it.What is the size attribute for in the XML? If it's telling the number of corresponding childs (for example, if <PORTS size="2"> means that there are two ports), I suggest you dump it and do the counting with the application itself. This applies to all occurances of this attribute.Other then that... I can't think of anything right now. Hm... I don't see the reason for the "all capitals" elements, but it makes no difference anyway, so go ahead.

Link to comment
Share on other sites

Thank you!I have taken on your advice and implemented.Here are my final amendmentsXML

<SCAMA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SCAMA - Schema.xsd">	<USERS>		<USER>name1</USER>		<USER>name2</USER>		<USER>name3</USER>		<USER>name4</USER>	</USERS>	<GROUPS>		<GROUP id="group1">			<PORTS>				<PORT id="port1">					<SOURCE_FILES>						<FILE type="txt">c:\group1\port1\source_file1.txt</FILE>						<FILE type="txt">c:\group1\port1\source_file2.txt</FILE>						<FILE type="txt">c:\group1\port1\source_file3.txt</FILE>						<FILE type="txt">c:\group1\port1\source_file4.txt</FILE>					</SOURCE_FILES>					<DEFINED_FREQS>						<START_FREQ units="Hz">12000000000</START_FREQ>						<STOP_FREQ units="Hz">12000000000</STOP_FREQ>						<POINTS>801</POINTS>					</DEFINED_FREQS>					<DESTINATION type="txt">c:\group1\port1\dest_file1.txt</DESTINATION>				</PORT>				<PORT id="port2">					<SOURCE_FILES>						<FILE type="txt">c:\group2\port2\source_file1.txt</FILE>						<FILE type="txt">c:\group2\port2\source_file2.txt</FILE>					</SOURCE_FILES>					<FREQ_MASTER type="txt">c:\group2\port2\freq_master.txt</FREQ_MASTER>					<DESTINATION type="txt">c:\group2\port2\dest_file1.txt</DESTINATION>				</PORT>			</PORTS>			<INSTALL>				<SOURCE>\\server\files\group1\</SOURCE>				<DESTINATION>\\comp_1\files\</DESTINATION>			</INSTALL>		</GROUP>	</GROUPS></SCAMA>

XSD

<?xml version="1.0" encoding="UTF-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">	<xs:element name="SCAMA">		<xs:complexType>			<xs:sequence>				<xs:element ref="USERS"/>				<xs:element ref="GROUPS"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="USERS">		<xs:complexType>			<xs:sequence>				<xs:element name="USER" type="NonBlankString" maxOccurs="unbounded"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="GROUPS">		<xs:complexType>			<xs:sequence>				<xs:element ref="GROUP" maxOccurs="unbounded"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<xs:element name="GROUP">		<xs:complexType>			<xs:sequence>				<xs:element ref="PORTS"/>				<xs:element ref="INSTALL"/>			</xs:sequence>			<xs:attribute name="id" type="NonBlankString" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="PORTS">		<xs:complexType>			<xs:sequence>				<xs:element ref="PORT" maxOccurs="unbounded"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<xs:element name="PORT">		<xs:complexType>			<xs:sequence>				<xs:element ref="SOURCE_FILES"/>				<xs:choice>					<xs:element ref="DEFINED_FREQS"/>					<xs:element name="FREQ_MASTER" type="FILE"/>				</xs:choice>				<xs:element name="DESTINATION" type="FILE"/>			</xs:sequence>			<xs:attribute name="id" type="NonBlankString" use="required"/>		</xs:complexType>	</xs:element>	<xs:element name="INSTALL">		<xs:complexType>			<xs:sequence>				<xs:element name="SOURCE" type="NonBlankString"/>				<xs:element name="DESTINATION" type="NonBlankString"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:element name="SOURCE_FILES">		<xs:complexType>			<xs:sequence>				<xs:element name="FILE" type="FILE" maxOccurs="unbounded"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<xs:element name="DEFINED_FREQS">		<xs:complexType>			<xs:sequence>				<xs:element name="START_FREQ" type="FREQS"/>				<xs:element name="STOP_FREQ" type="FREQS"/>				<xs:element name="POINTS" type="xs:integer"/>			</xs:sequence>		</xs:complexType>	</xs:element>	<!-- ############################################################### -->	<xs:complexType name="FILE">		<xs:simpleContent>			<xs:extension base="NonBlankString">				<xs:attribute name="type" type="FileType" use="required"/>			</xs:extension>		</xs:simpleContent>	</xs:complexType>	<xs:complexType name="FREQS">		<xs:simpleContent>			<xs:extension base="NonBlankString">				<xs:attribute name="units" type="UnitsEnumType" use="required"/>			</xs:extension>		</xs:simpleContent>	</xs:complexType>	<xs:simpleType name="UnitsEnumType">		<xs:restriction base="NonBlankString">			<xs:enumeration value="Hz"/>			<xs:enumeration value="kHz"/>			<xs:enumeration value="MHz"/>			<xs:enumeration value="GHz"/>		</xs:restriction>	</xs:simpleType>	<xs:simpleType name="FileType">		<xs:restriction base="NonBlankString">			<xs:enumeration value="txt"/>			<xs:enumeration value="citi"/>			<xs:enumeration value="hdf"/>		</xs:restriction>	</xs:simpleType>	<xs:simpleType name="NonBlankString">		<xs:restriction base="xs:string">			<xs:minLength value="1"/>			<xs:whiteSpace value="collapse"/>		</xs:restriction>	</xs:simpleType></xs:schema>

Link to comment
Share on other sites

One last thing I noticed. It's more of a personal preference, but it could do you some good too. The whole definition of:

<xs:simpleType name="UnitsEnumType">		<xs:restriction base="NonBlankString">			<xs:enumeration value="Hz"/>			<xs:enumeration value="kHz"/>			<xs:enumeration value="MHz"/>			<xs:enumeration value="GHz"/>		</xs:restriction>	</xs:simpleType>

Could be reduced to this:

<xs:simpleType name="UnitsEnumType">		<xs:restriction base="NonBlankString">			<xs:pattern value="(k|M|G)?Hz"/>		</xs:restriction>	</xs:simpleType>

The effect is the same, but in less code. And, if you decide to support THz and PHz, you can do so by just adding "|T|P" right between "G" and ")". All in all, when you have repeating words in enumerations (in this case: Hz), regular expressions are a good way to reduce space. I'm not sure of efficiency, but I think there's a benefit in that too.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...