Jump to content

Allowing specific permutations of attributes/elements


drokulix

Recommended Posts

Sorry about the title...I couldn't figure out anything coherent to title the topic. Anyway, I'm new fish to Schema and I'm attempting to build a validator for XML relating to public transit.There is a root <segment> element which may contain exactly one or two of the following: <point/>, <pointStart/>, <pointEnd/>. Further, there can be at most one start, and at most one end. Since I come from a Perl background, consider the following regexp that has P standing in for <point/>, S for <pointStart/>, and E for <pointEnd/>:

P?[PSE]|S[PE]|E[PS]

Or, to appease certain engines that consider this nondeterministic,

P[PSE]?|S[PE]?|E[PS]?

The idea being that there must be one or two of them and, if two, they cannot be the same unless they are both plain <point/>s.Here is a schema that I've tested by brute force (using xmllint) to work in all cases:

<?xml version="1.0" ?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">	<xs:element name="segment">		<xs:complexType>			<xs:choice>				<xs:sequence>					<xs:element name="point"/>					<xs:choice minOccurs="0">						<xs:element name="point"/>						<xs:element name="pointStart"/>						<xs:element name="pointEnd"/>					</xs:choice>				</xs:sequence>				<xs:sequence>					<xs:element name="pointStart"/>					<xs:choice minOccurs="0">						<xs:element name="point"/>						<xs:element name="pointEnd"/>					</xs:choice>				</xs:sequence>				<xs:sequence>					<xs:element name="pointEnd"/>					<xs:choice minOccurs="0">						<xs:element name="point"/>						<xs:element name="pointStart"/>					</xs:choice>				</xs:sequence>			</xs:choice>		</xs:complexType>	</xs:element></xs:schema>

First question: Do I really have to spell it out the way I have, or is there a simpler equivalent? The idea of removing unnecessary ordering using <xs:all/> is tantalizing, but I can't think of a way to make it work.Second question: If I wanted to replace <pointStart/> and <pointEnd/> with <point type="start"/> and <point type="end"/>, respectively, would it be possible, and how would I go about it if so? (This question is the genesis of this post. It seems messy to have to move something that's obviously an attribute into the name just to make validation possible...)Thoughts?

Link to comment
Share on other sites

So, in the whole document there can be only one Start, and ony one End, right?Well, then, you can have <point type="start"/> and <point type="end"/> if you label the type attribute as of type xs:ID. However, be warned that this would mean a "start" could appear after the "end". If that's no problem, then you could do:

<?xml version="1.0"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">	<xs:element name="segment">		<xs:complexType>			<xs:sequence>				<xs:element name="point" maxOccurs="unbounded">					<xs:complexType>						<xs:attribute name="type">							<xs:simpleType>								<xs:restriction base="xs:ID">									<xs:enumeration value="start"/>									<xs:enumeration value="end"/>									<xs:pattern value=".+"/>								</xs:restriction>							</xs:simpleType>						</xs:attribute>					</xs:complexType>				</xs:element>			</xs:sequence>		</xs:complexType>	</xs:element></xs:schema>

Also note that with the line

<xs:pattern value=".+"/>

I'm allowing other points to have IDs too. Remove that line if you want to leave other points IDless.Last, but certainly not least important, beware that a "start" and "end" may not appear at all. Just having

<segment>	<point/></segment>

or

<segment>	<point/>	<point/></segment>

would be legal.

Link to comment
Share on other sites

So, in the whole document there can be only one Start, and ony one End, right?
Unfortunately, that's not the case...a subsequent version of the schema will allow multiple <segment/> elements, each potentially with its own start and end.It doesn't matter if start and end appear out of order as long as they are marked; order only matters if both points are unmarked, in which case the first is assumed the start.Thanks
Link to comment
Share on other sites

In that case, I'm afraid the combination you've used at first is best. There's no way to make IDs unique only per region.Of course, you can always drop the marks, and as you say, treat the first one as a start, and the last one as an end.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...