Errors using SvcUtil.exe on a wsdl to generate proxy class - xs:group element - xsd

I'm trying to use SvcUtil against a wsdl file to generate proxy classes, but I'm getting an element missing error that I think is related to schema group elements. Does anyone know for a fact if svcutil can handle ? And if so will it handle xs:group elements that have ref attributes that point to the group definition that lives in another schema file?
SvcUtil.exe Command (included the paths to the xsd files as well):
d:\codegen\svcutil.exe d:\codegen\RPE\ProtocolStateManager.wsdl d:\codegen\RPE\schema\RPE.xsd d:\codegen\RPE\schema\PORT_MT100001UV.xsd d:\codegen\RPE\schema\coreschemas\infrastructureRoot.xsd d:\codegen\RPE\schema\coreschemas\dataTypes.xsd d:\codegen\RPE\schema\coreschemas\voc.xsd /l:cs
The error is:
Error: Cannot import wsdl:portType
Detail: An exception was thrown while
running a WSDL import extension:
System.ServiceModel.Description.XmlSerializerMessageContractImporter
Error: Group
InfrastructureRootElements is missing.
XPath to Error Source:
//wsdl:definitions[#targetNamespace='urn:ihe:qrph:rpe:2009']/wsdl:portType[#name= 'ProtocolStateManager']
ProtocolStateManager.wsdl:
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="ProtocolStateManager"
targetNamespace="urn:ihe:qrph:rpe:2009"
xmlns:rpe="urn:ihe:qrph:rpe:2009"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/">
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TYPE DEFINITION - List of services participating in this BPEL process
The default output of the BPEL designer uses strings as input and
output to the BPEL Process. But you can define or import any XML
Schema type and use them as part of the message types.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:ihe:qrph:rpe:2009">
<include schemaLocation="schema\RPE.xsd"/>
</schema>
</types>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MESSAGE TYPE DEFINITION - Definition of the message types used as
part of the port type defintions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<message name="EnterPatientRequestRequestMessage">
<part name="payload" element="rpe:EnterPatientRequest"/>
</message>
<message name="EnterPatientRequestResponseMessage">
<part name="payload" element="rpe:EnterPatientRequest"/>
</message>
<message name="PatientScreeningVisitsScheduledRequestMessage">
<part name="payload" element="rpe:PatientScreeningVisitsScheduled"/>
</message>
<message name="PatientScreeningVisitsScheduledResponseMessage">
<part name="payload" element="rpe:PatientScreeningVisitsScheduled"/>
</message>
<message name="PatientScreeningVisitRecordedRequestMessage">
<part name="payload" element="rpe:PatientScreeningVisitRecorded"/>
</message>
<message name="PatientScreeningVisitRecordedResponseMessage">
<part name="payload" element="rpe:PatientScreeningVisitRecorded"/>
</message>
<message name="EnrollPatientRequestRequestMessage">
<part name="payload" element="rpe:EnrollPatientRequest"/>
</message>
<message name="EnrollPatientRequestResponseMessage">
<part name="payload" element="rpe:EnrollPatientRequest"/>
</message>
<message name="PatientStudyVisitsScheduledRequestMessage">
<part name="payload" element="rpe:PatientStudyVisitsScheduled"/>
</message>
<message name="PatientStudyVisitsScheduledResponseMessage">
<part name="payload" element="rpe:PatientStudyVisitsScheduled"/>
</message>
<message name="PatientStudyVisitRecordedRequestMessage">
<part name="payload" element="rpe:PatientStudyVisitRecorded"/>
</message>
<message name="PatientStudyVisitRecordedResponseMessage">
<part name="payload" element="rpe:PatientStudyVisitRecorded"/>
</message>
<message name="AlertProtocolStateMessage">
<part name="payload" element="rpe:AlertProtocolState"/>
</message>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PORT TYPE DEFINITION - A port type groups a set of operations into
a logical service unit.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- portType implemented by the ProtocolStateManager BPEL process -->
<portType name="ProtocolStateManager">
<operation name="EnterPatientRequest">
<input message="rpe:EnterPatientRequestRequestMessage"/>
<output message="rpe:EnterPatientRequestResponseMessage"/>
</operation>
<operation name="PatientScreeningVisitsScheduled">
<input message="rpe:PatientScreeningVisitsScheduledRequestMessage"/>
<output message="rpe:PatientScreeningVisitsScheduledResponseMessage"/>
</operation>
<operation name="RecordPatientScreeningVisit">
<input message="rpe:PatientScreeningVisitRecordedRequestMessage"/>
<output message="rpe:PatientScreeningVisitRecordedResponseMessage"/>
</operation>
<operation name="EnrollPatientRequest">
<input message="rpe:EnrollPatientRequestRequestMessage"/>
<output message="rpe:EnrollPatientRequestResponseMessage"/>
</operation>
<operation name="PatientStudyVisitsScheduled">
<input message="rpe:PatientStudyVisitsScheduledRequestMessage"/>
<output message="rpe:PatientStudyVisitsScheduledResponseMessage"/>
</operation>
<operation name="RecordPatientStudyVisit">
<input message="rpe:PatientStudyVisitRecordedRequestMessage"/>
<output message="rpe:PatientStudyVisitRecordedResponseMessage"/>
</operation>
</portType>
<portType name="ProtocolStateManagerCallback">
<operation name="onAlertProtocolState">
<input message="rpe:AlertProtocolStateMessage"/>
</operation>
</portType>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PARTNER LINK TYPE DEFINITION
the ProtocolStateManager partnerLinkType binds the provider and
requester portType into an asynchronous conversation.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<plnk:partnerLinkType name="ProtocolStateManager">
<plnk:role name="ProtocolStateManagerProvider">
<plnk:portType name="rpe:ProtocolStateManager"/>
</plnk:role>
<plnk:role name="ProtocolStateManagerCallbackListener">
<plnk:portType name="rpe:ProtocolStateManagerCallback"/>
</plnk:role>
</plnk:partnerLinkType>
</definitions>
RPE.xsd (reference by ProtocolStateManager.wsdl):
<schema attributeFormDefault="unqualified" elementFormDefault="qualified"
targetNamespace="urn:ihe:qrph:rpe:2009"
xmlns:rpe="urn:ihe:qrph:rpe:2009"
xmlns:v3="urn:hl7-org:v3"
xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="urn:hl7-org:v3" schemaLocation="PORT_MT100001UV.xsd"/>
<element name="RetrieveProtocolDef" type="rpe:RetrieveProtocolDefType"/>
<element name="EnterPatientRequest" type="rpe:EnterPatientRequestType"/>
<element name="EnrollPatientRequest" type="rpe:EnrollPatientRequestType"/>
<element name="PatientScreeningVisitsScheduled" type="rpe:PatientScreeningVisitsScheduledType"/>
<element name="PatientScreeningVisitRecorded" type="rpe:PatientScreeningVisitRecordedType"/>
<element name="PatientStudyVisitsScheduled" type="rpe:PatientStudyVisitsScheduledType"/>
<element name="PatientStudyVisitRecorded" type="rpe:PatientStudyVisitRecordedType"/>
<element name="AmendProtocolDef" type="rpe:AmendProtocolDefType"/>
<element name="AlertProtocolState" type="rpe:AlertProtocolStateType"/>
<!-- need patient information and study information
EnterPatientRequestType can also be used for the return of candidateID?-->
<complexType name="RetrieveProtocolDefType">
<sequence>
<element name="query" type="string"/>
<element name="protocolDef" type="string"/>
</sequence>
</complexType>
<complexType name="EnterPatientRequestType">
<sequence>
<element name="patient" type="rpe:PatientType"/>
<element name="study" type="v3:PORT_MT100001UV.Study"/>
</sequence>
</complexType>
<!-- need patient for candidateID of the patient being scheduled for screening visits
need studyID to associate the candidate with the study
need schedule information-->
<complexType name="PatientScreeningVisitsScheduledType">
<sequence>
<element name="patient" type="rpe:PatientType"/>
<element name="studyID" type="v3:II"/>
<element name="schedule" type="rpe:ScreeningVisitScheduleType"/>
</sequence>
</complexType>
<!-- need patient for candidateID of patient being recorded for screening visit
need studyID to associate the candidate with the study
need visit information for the screening visit being recorded-->
<complexType name="PatientScreeningVisitRecordedType">
<sequence>
<element name="patient" type="rpe:PatientType"/>
<element name="studyID" type="v3:II"/>
<element name="visit" type="rpe:ScreenVisitType"/>
</sequence>
</complexType>
<!-- need patient information and study information
EnterPatientRequestType can also be used for the return of subjectID?-->
<complexType name="EnrollPatientRequestType">
<sequence>
<element name="patient" type="rpe:PatientType"/>
<element name="study" type="v3:PORT_MT100001UV.Study"/>
</sequence>
</complexType>
<!-- need patient for subjectID of the patient being scheduled for visits
need studyID to associate the subject with the study
need schedule information-->
<complexType name="PatientStudyVisitsScheduledType">
<sequence>
<element name="patient" type="rpe:PatientType"/>
<element name="studyID" type="v3:II"/>
<element name="schedule" type="rpe:StudyVisitScheduleType"/>
</sequence>
</complexType>
<!-- need patient for subjectID of patient being recorded for visit
need studyID to associate the subject with the study
need visit information for the visit being recorded-->
<complexType name="PatientStudyVisitRecordedType">
<sequence>
<element name="patient" type="rpe:PatientType"/>
<element name="studyID" type="v3:II"/>
<element name="visit" type="rpe:StudyVisitType"/>
</sequence>
</complexType>
<!-- patient information should NOT include emrID?
should contain placeholder for candidateID and subjectID
what specific demographics data is needed?
Should this be a generic type so that an XML standard can be passed?-->
<complexType name="PatientType">
<sequence>
<element name="candidateID" type="string"/>
<element name="subjectID" type="string"/>
<element name="name" type="string"/>
<element name="address" type="string"/>
<element name="dob" type="string"/>
</sequence>
</complexType>
<!-- studyID to identify the study
should studyData be a generic type to store an XML standard
<complexType name="StudyType">
<sequence>
<element name="studyID" type="string"/>
<element name="studyData" type="string"/>
</sequence>
</complexType>-->
<complexType name="ScreenVisitType">
<sequence>
<element name="visitID" type="string"/>
<element name="candidateID" type="string"/>
<element name="date" type="string"/>
<element name="screenVisitData" type="string"/>
</sequence>
</complexType>
<complexType name="StudyVisitType">
<sequence>
<element name="visitID" type="string"/>
<element name="subjectID" type="string"/>
<element name="date" type="string"/>
<element name="studyVisitData" type="string"/>
</sequence>
</complexType>
<complexType name="ScreeningVisitScheduleType">
<sequence>
<element name="visit" type="rpe:ScreenVisitType" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="StudyVisitScheduleType">
<sequence>
<element name="visit" type="rpe:StudyVisitType" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="AmendProtocolDefType">
<sequence>
<element name="protocolDef" type="string"/>
</sequence>
</complexType>
<complexType name="AlertProtocolStateType">
<sequence>
<element name="patient" type="rpe:PatientType"/>
<element name="study" type="v3:PORT_MT100001UV.Study"/>
</sequence>
</complexType>
</schema>
Snippet from PORT_MT100001UV.xsd (Referenced by RPE.xsd) - notice the "InfrastructureRootElements" xs:group:
<xs:complexType name="PORT_MT100001UV.Access">
<xs:sequence>
<xs:group ref="InfrastructureRootElements"/>
<xs:element name="id" type="II" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="targetSiteCode" type="CD" minOccurs="0" maxOccurs="1"/>
<xs:choice>
<xs:choice>
<xs:element name="accessedPerson" type="PORT_MT100001UV.Person" nillable="true"
minOccurs="0"
maxOccurs="1"/>
<xs:element name="accessedNonPersonLivingSubject"
type="PORT_MT100001UV.NonPersonLivingSubject"
nillable="true"
minOccurs="0"
maxOccurs="1"/>
</xs:choice>
<xs:element name="accessedProduct" type="PORT_MT100001UV.Product" nillable="true"
minOccurs="0"
maxOccurs="1"/>
</xs:choice>
</xs:sequence>
<xs:attributeGroup ref="InfrastructureRootAttributes"/>
<xs:attribute name="nullFlavor" type="NullFlavor" use="optional"/>
<xs:attribute name="classCode" type="RoleClassAccess" use="required"/>
</xs:complexType>
infrastructureRoot.xsd (reference by PORT_MT100001UV.xsd) notice the definition of the InfrastructureRootElements group here - this is the same group from the above schema that has the ref attribute:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns:mif="urn:hl7-org:v3/mif" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:v3="urn:hl7-org:v3"
xmlns:ex="urn:hl7-org/v3-example"
elementFormDefault="qualified">
<xs:annotation xmlns="urn:hl7-org:v3">
<xs:documentation>Source Information...</xs:documentation>
</xs:annotation>
<xs:include schemaLocation="voc.xsd"/>
<xs:include schemaLocation="datatypes.xsd"/>
<xs:group name="InfrastructureRootElements">
<xs:sequence>
<xs:element name="realmCode" type="CS" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="typeId" type="II" minOccurs="0" maxOccurs="1"/>
<xs:element name="templateId" type="II" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:group>
<xs:attributeGroup name="InfrastructureRootAttributes"/>
</xs:schema>

I found this tool - WSCF Blue - from a post on msdn forums. It got me past my errors and also looks to offer quite a bit more in terms of functionality.

I'm not sure about SvcUtil, but for XSD.exe and WSDL.exe you have to specify all the files that are used by the .xsd file, because they don't recognize elements. Maybe my post will help you, too: http://seanmcilvenna.com/blog/7-general/30-xca-implementation

Related

XSD all-or-nothing group

I want to match these two documents:
<a>
<b/>
</a>
and:
<a>
<b/>
<c/>
<d/>
</a>
That is, there must be either neither of c and d or both of c and d.
I've tried to have a choice of two sequences, but I get: "The content model is
not determinist.", I guess because the choice has to be disambiguated on the
first element, which is the same for the two different documents.
You can put c and d inside a sequence group with minOccurs=0. Like this:
<element name="a">
<complexType>
<sequence>
<element name="b" />
<sequence minOccurs="0">
<element name="c" />
<element name="d" />
</sequence>
</sequence>
</complexType>
</element>
If you want c and d to be able to appear in any order, you can do this:
<element name="a">
<complexType>
<sequence>
<element name="b" />
<choice minOccurs="0">
<sequence>
<element name="c" />
<element name="d" />
</sequence>
<sequence>
<element name="d" />
<element name="c" />
</sequence>
</choice>
</sequence>
</complexType>
</element>
Obviously, this approach does not scale well if you have more than two members in the group.

Using Unique without namespace declaration

Can anyone explain why a unique identity constraint on an eleement would not work unless the elements are namespace prefixed? This leads me to beleive that unique constraints can only be applied to gloabbly defined elements. I am not sure why a unique constratint couldnt be put on a locally defiened element. In my sample schema below, i have a unique constraint defined on Writer.name which works fine. I also defined one on Test.name which does not work unless I make Test and its chiled name, global elements.
<schema targetNamespace="http://www.amica.com/dev_v1/Test" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.amica.com/dev_v1/Test" elementFormDefault="unqualified" attributeFormDefault="unqualified">
<element name="MyMusic">
<complexType>
<sequence>
<element name="Song" type="tns:SongType"/>
</sequence>
</complexType>
</element>
<complexType name="SongType">
<sequence>
<element ref="tns:Artists"/>
<element ref="tns:Writers"/>
<element name="Tests">
<complexType>
<sequence>
<element name="Test" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="name"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
<unique name="UniqueTestName">
<selector xpath="Test"/>
<field xpath="name"/>
</unique>
</element>
</sequence>
</complexType>
<element name="Artist">
<complexType>
<simpleContent>
<extension base="string">
<attribute name="aID" use="required">
<simpleType>
<restriction base="string"/>
</simpleType>
</attribute>
</extension>
</simpleContent>
</complexType>
</element>
<element name="Writer">
<complexType>
<sequence>
<element ref="tns:name"/>
</sequence>
</complexType>
</element>
<element name="Artists">
<annotation>
<documentation>Test unique constraint on an attrbute</documentation>
</annotation>
<complexType>
<sequence>
<element ref="tns:Artist" maxOccurs="unbounded"/>
</sequence>
</complexType>
<unique name="UniqueArtistKey">
<selector xpath="tns:Artist"/>
<field xpath="#aID"/>
</unique>
</element>
<element name="Writers">
<annotation>
<documentation>Test unique constraint on an element</documentation>
</annotation>
<complexType>
<sequence>
<element ref="tns:Writer" maxOccurs="unbounded"/>
</sequence>
</complexType>
<unique name="UniqueWriterName">
<selector xpath="tns:Writer"/>
<field xpath="tns:name"/>
</unique>
</element>
<element name="name" type="string"/>
</schema>

how to enforce atleast one occurence for 2 element types in XSD schema

I need to develop an xsd for the scenario. where i have 2 element of types Server1 and Server2. There can be any number of occurances for Server1 and Server2 but atleast one of the occurance is mandatory either Server1 or Server2.
<element name="Server1">
<complexType>
<sequence>
<element name="hostName" type="string"/>
<element name="portNumber" type="integer"/>
<element name="userName" type="string"/>
</sequence>
</complexType>
</element>
<element name="Server2">
<complexType>
<sequence>
<element name="hostName" type="string"/>
<element name="portNumber" type="integer"/>
</sequence>
</complexType>
</element>
Thanks
Ravi
You can wrap them to choice schema element with maxOccurs attribute set to unbounded.
Sample:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<element name="root">
<complexType>
<choice maxOccurs="unbounded">
<element name="Server1">
<complexType>
<sequence>
<element name="hostName" type="string"/>
<element name="portNumber" type="integer"/>
<element name="userName" type="string"/>
</sequence>
</complexType>
</element>
<element name="Server2">
<complexType>
<sequence>
<element name="hostName" type="string"/>
<element name="portNumber" type="integer"/>
</sequence>
</complexType>
</element>
</choice>
</complexType>
</element>
</schema>
I'm not sure it's the best possibility by any means, but one possibility would be for Server1 and Server2 to be just type names, and then create an element that's a union of Server1 and Server2.
<xsd:comlexType name=Server1>
<sequence>
// ...
</sequence>
</xsd:complextype>
<xsd:complexType name=Server2>
// ...
</xsd:complexType>
<element name="Server">
<xsd:union memberTypes = "Server1 Server2" />
</element>

JAXB List of Choice

I have following schema
<complexType name="BookShelf">
<sequence>
<element name="newBook" type="string" minOccurs="0" maxOccurs="unbounded"/>
<element name="oldBook" type="string" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
XJC generates BookShelf class with two lists, one for newBook and one for oldBook. Excellent!
Now I want books to appear in any order. So I rewrite my schema to:
<complexType name="BookShelf">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element name="newBook" type="string"/>
<element name="oldBook" type="string"/>
</choice>
</sequence>
</complexType>
But now XJC generates BookShelf with only one list newBookOrOldBook of type List<JAXBElement<String>>.
I don't care about the order in which books appear and I want to allow XML writer to specify books in any order he\she wishes, but I still want books of each type as List in generated BookShelf class. Is there any way I can achieve this?
You can use the Simplify plugin from JAXB2 Basics. It can simplify #XmlElements and #XmlElementRefs properties, which makes things a lot easier, if you don't really care about the order. Here's an example (excerpt from the documentation):
Consider the following choice:
<xs:complexType name="typeWithReferencesProperty">
<xs:choice maxOccurs="unbounded">
<xs:element name="a" type="someType"/>
<xs:element name="b" type="someType"/>
</xs:choice>
</xs:complexType>
This will normally generate a property like:
#XmlElementRefs({
#XmlElementRef(name = "a", type = JAXBElement.class),
#XmlElementRef(name = "b", type = JAXBElement.class)
})
protected List<JAXBElement<SomeType>> aOrB;
You can use the simplify:as-element-property element to remodel this complex property as two element properties or simplify:as-reference-property as two reference properties.
Not that in the case of a reference property, you have to customize one of the xs:element and not the xs:choice.
<xs:complexType name="typeWithReferencesProperty">
<xs:choice maxOccurs="unbounded">
<xs:element name="a" type="someType">
<xs:annotation>
<xs:appinfo>
<simplify:as-element-property/>
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="b" type="someType"/>
</xs:choice>
</xs:complexType>
Results in:
#XmlElement(name = "a")
protected List<SomeType> a;
#XmlElement(name = "b")
protected List<SomeType> b;
Maybe something like this?
<schema
elementFormDefault = "qualified"
xmlns = "http://www.w3.org/2001/XMLSchema"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:tns = "urn:cheeso.examples.2009.05.listofbooks"
targetNamespace = "urn:cheeso.examples.2009.05.listofbooks"
>
<element name="Shelf" nillable="true" type="tns:BookShelf" />
<complexType name="BookShelf">
<sequence>
<element minOccurs="0" maxOccurs="1" name="Store" type="tns:ArrayOfChoice1" />
</sequence>
</complexType>
<complexType name="ArrayOfChoice1">
<choice minOccurs="0" maxOccurs="unbounded">
<element minOccurs="1" maxOccurs="1" name="newBook" nillable="true" type="tns:newBook" />
<element minOccurs="1" maxOccurs="1" name="oldBook" nillable="true" type="tns:oldBook" />
</choice>
</complexType>
<complexType name="Book">
<attribute name="name" type="string" />
</complexType>
<complexType name="newBook">
<complexContent mixed="false">
<extension base="tns:Book" />
</complexContent>
</complexType>
<complexType name="oldBook">
<complexContent mixed="false">
<extension base="tns:Book" />
</complexContent>
</complexType>
</schema>
Of course you could simplify to
<schema
elementFormDefault = "qualified"
xmlns = "http://www.w3.org/2001/XMLSchema"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:tns = "urn:cheeso.examples.2009.05.listofbooks"
targetNamespace = "urn:cheeso.examples.2009.05.listofbooks"
>
<element name="Shelf" nillable="true" type="tns:BookShelf" />
<complexType name="BookShelf">
<sequence>
<element minOccurs="0" maxOccurs="1" name="Store" type="tns:ArrayOfChoice1" />
</sequence>
</complexType>
<complexType name="ArrayOfChoice1">
<choice minOccurs="0" maxOccurs="unbounded">
<element minOccurs="1" maxOccurs="1" name="newBook" nillable="true" type="xs:string" />
<element minOccurs="1" maxOccurs="1" name="oldBook" nillable="true" type="xs:string" />
</choice>
</complexType>
</schema>
I don't think this is possible in JAXB, without writing some custom java or XSLT.
JAXB isn't very good at mapping between objects and xml that have different structure, like yours. Also, the ordering of the old book with respect to new books in XML would be lost when converted to two separate lists in Java, and JAXB generally wants to preserve information.
The following does not answer your question, but maybe it's a step towards what you want:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="bookShelf" type="BookShelf"/>
<xs:complexType name="BookShelf">
<xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="newBook" minOccurs="0" type="xs:string"/>
<xs:element name="oldBook" minOccurs="0" type="xs:string"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:schema>
I haven't tried this with JAXB, but I think it will generate a list of a class with two fields, newBook and oldBook. So, you don't have to cast or use instanceof, but can just check for null to see which one it is. As I said, it's not a solution, but maybe a little bit closer.
I think I have to refuse the idea of mixing lists of different elements in one element (mixing old and new books on a bookself), especially because I'm planning to reference lists of those elements (new and old books lists) in other elements. If I don't it quickly became a nightmare in java code. I ended with the following schema:
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.example.org/books"
targetNamespace="http://www.example.org/books"
elementFormDefault="qualified"
>
<complexType name="BookShelf">
<sequence>
<element name="newBooks" type="tns:NewBookList" minOccurs="0" />
<element name="oldBooks" type="tns:OldBookList" minOccurs="0" />
</sequence>
</complexType>
<complexType name="NewBookList">
<sequence>
<element name="newBook" type="tns:NewBook" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="OldBookList">
<sequence>
<element name="oldBook" type="tns:OldBook" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="NewBook" />
<complexType name="OldBook" />
</schema>
Thanks everyone for helping me realize this. This schema will lead to more clear and simple Java code as well as to more readable and predictable XML document.

XSD validation for unsorted and only one unbounded item

I have a xml file like this:
<customer>
<field1 />
<field2 />
<field3>
<item1 />
</field3>
<field3>
<item1 />
</field3>
</customer>
field* can appear in any order and only field3 can appear more than once.
How can I create a XSD file to validate this?
Thank you!
Try this
I'm not a guru, but this appears to work.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="customer" type="customerType"/>
<xs:complexType name="customerType">
<xs:sequence>
<xs:element name="field1" minOccurs="1" maxOccurs="1">
</xs:element>
<xs:element name="field2" minOccurs="1" maxOccurs="1">
</xs:element>
<xs:element name="field3" type="field3Type"
minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="field3Type">
<xs:sequence>
<xs:element name="item1">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
tools
I used XML Copy Editor, but there are loads of editors which will validate XML.
links
You might also be interested in this article about generating an XSD from an XML file.
Hum, this is the kind of work xsd is really not handy for. Anyway, this should do the trick if I did not make a mistake:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/NewXMLSchema"
xmlns:tns="http://www.example.org/NewXMLSchema" elementFormDefault="qualified">
<element name="customer" type="tns:customerType"/>
<complexType name="customerType">
<sequence>
<element>
<complexType>
<all>
<element>
<complexType>
<sequence>
<element ref="tns:field3" maxOccurs="unbounded"/>
<element ref="tns:field1" maxOccurs="1"/>
</sequence>
</complexType>
</element>
<element>
<complexType>
<sequence>
<element ref="tns:field3" maxOccurs="unbounded"/>
<element ref="tns:field2" maxOccurs="1"/>
</sequence>
</complexType>
</element>
<element>
<complexType>
<sequence>
<element ref="tns:field3" maxOccurs="unbounded"/>
<element ref="tns:field4" maxOccurs="1"/>
</sequence>
</complexType>
</element>
</all>
</complexType>
</element>
<element ref="tns:field3" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="field1Container"/>
<complexType name="field2Container"/>
<complexType name="field3Type">
<sequence>
<element name="item1"/>
</sequence>
</complexType>
<complexType name="field4Container"/>
<element name="field3" type="tns:field3Type"/>
<element name="field1"/>
<element name="field2"/>
<element name="field4"/>
</schema>

Resources