I have below xsd elements.
<xsd:element name="requestOne" type="tns:RequestOne"/>
<xsd:complexType name="RequestOne">
<xsd:annotation>
<xsd:documentation>some comment</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="id" type="xsd:string" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="requestTwo" type="tns:RequestTwo"/>
<xsd:complexType name="RequestTwo">
<xsd:annotation>
<xsd:documentation>other comment</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="id" type="xsd:string" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
It has two complex elements but inside them there is duplicated code. How can i refactor above code?
Thanks!
Instead of creating a new element you can use ref to refer to an existing one, tns in the sample below refers to the name space defined by the schema
<xsd:element name="id" type="xsd:string"/>
...
<xsd:complexType name=RequestOne">
<xsd:sequence>
<xsd:element ref="tns:id" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
...
Though, this does not really reduces the number of characters to write, in that simple case. You might even have a look at how to define abstract types which, similar to object orientated languages, get inherited by children:
<xsd:complexType name="AbstractType" abstract="true">
<xsd:sequence>
<xsd:element name"BaseType">
<xs:complexType>
<xsd:sequence>
<xsd:element name="id" type="xsd:string" minOccurs="1" maxOccurs="1" >
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
the children now need to inherit from the abstract type in the following manner:
<xsd:complexType name="ChildOne">
<xsd:complexContent>
<xsd:extension base="tns:AbstractType">
<xsd:element name="newElement" type="xsd:string" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
Where newElement is just a new element defined by the child.
Edit: to be more precise, the id element is not really inherited like in an object oriented language but you achieve the same effect. The difference is, that you have to add the base-type within the XML of the concrete realization.
<ChildOne>
<BaseType>
<id>someId</id>
</BaseType>
<!-- elements defined by child one goes here -->
<newElement>new Element</newElement>
</ChildOne>
Related
I'm trying to use some open-source software for RFID services (GitHub: fosstrak capturing application) from a few years ago and there's this error that I can't fix.
(null: 3, 230): cvc-elt.1: Cannot find the declaration of element 'change-set'.
I'm using Docker to containerise the application running Tomcat7 with Java8.
The XML looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<change-set xmlns="http://drools.org/drools-5.0/change-set"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://drools.org/drools-5.0/change-set.xsd http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd">
<add>
<resource source="classpath:drools/SimpleEPCISDocument.drl" type="DRL" />
</add>
</change-set>
And the XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="http://drools.org/drools-5.0/change-set"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:change-set="http://drools.org/drools-5.0/change-set">
<xsd:import namespace="http://www.w3.org/2001/XMLSchema-instance"/>
<xsd:element name="change-set">
<xsd:complexType>
<xsd:choice>
<xsd:element ref="change-set:add"/>
<xsd:element ref="change-set:remove"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
<xsd:element name="add">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="unbounded" ref="change-set:resource"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="remove">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="unbounded" ref="change-set:resource"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="resource">
<xsd:complexType>
<xsd:sequence>
<xsd:any minOccurs="0"/>
<xsd:element minOccurs="0" ref="change-set:decisiontable-conf"/>
</xsd:sequence>
<!-- URL to the resource, can be file based -->
<xsd:attribute name="source" use="required" type="xsd:anyURI"/>
<!-- for example, DRL, or PKG -->
<xsd:attribute name="type" use="required" type="xsd:string"/>
<xsd:attribute name="basicAuthentication" type="xsd:string"/>
<xsd:attribute name="username" type="xsd:string"/>
<xsd:attribute name="password" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="decisiontable-conf">
<xsd:complexType>
<xsd:attribute name="input-type" use="required" type="xsd:NCName"/>
<xsd:attribute name="worksheet-name" use="required" type="xsd:NCName"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Change
xs:schemaLocation="http://drools.org/drools-5.0/change-set.xsd [...]
to
xs:schemaLocation="http://drools.org/drools-5.0/change-set [...]
because schemaLocation must be a series of pairs of namespace URIs and XSD locations. In this case, the namespace URI is http://drools.org/drools-5.0/change-set, which matches the namespace of the root element in your XML and the target namespace of your XSD.
See also
How to reference a local XML Schema file correctly?
You'll also have to deal with a subsequent Unique Particle Attribute issue, but that's a separate matter deserving its own question if you're unable to resolve. Start with XSD validation - ANY in SEQUENCE ("Unique Particle Attribution").
This is a continuity of My question
Assume below is my xsd file,
Updated XSD file
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/wm" xmlns="http://www.example.com/wm" elementFormDefault="qualified" version="1.0">
<xsd:include schemaLocation="Comm.xsd" />
<xsd:element name="testEame1">
<xsd:annotation>
<xsd:documentation> test </xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="id" type="xsd:string" minOccurs="1" />
<xsd:element name="session" type="rawSess" minOccurs="1" />
</xsd:sequence>
<xsd:attribute name="pid" type="xsd:integer" use="required" />
<xsd:attribute name="version" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
references another XSD which has type defined,
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://www.example.com/wm" xmlns="http://www.example.com/wm" elementFormDefault="qualified">
<xsd:complexType name="rawSess">
<xsd:sequence>
<xsd:element name="oldSessionVersion" type="Sessiontype1" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="sessInfo">
<xsd:sequence>
<xsd:element name="newSessionVersion" type="Sessiontype2" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Sessiontype1">
<xsd:sequence>
<xsd:element name="ele1" type="xsd:string" minOccurs="0" />
<xsd:element name="ele2" type="xsd:string" />
<xsd:element name="ele3" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Sessiontype2">
<xsd:sequence>
<xsd:element name="nele1" type="xsd:integer" minOccurs="0" />
<xsd:element name="nele2" type="xsd:integer" />
<xsd:element name="nele3" type="xsd:integer" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
In the above xml, for element session , I want it to have only two types like below. Either sessInfo or rawSess
<xsd:element name="session" type='sessInfo| rawSess' minOccurs="1"/>
Update Note : userDefinedtypes are complex types.
How can I configure my xsd to achieve this
If userDefinedType1 and userDefinedType2 are simple atomic types, then define a union type:
<xs:element name="session" type="one-or-two"/>
<xs:simpleType name="one-or-two">
<xs:union memberTypes="userDefinedType1 userDefinedType2"/>
</xs:simpleType>
We now know that they are actually complex types. Define a type
<xs:complexType name="eitherType">
<xs:choice>
<xs:sequence>... content model of alternative 1</xs:sequence>
<xs:sequence>... content model of alternative 2</xs:sequence>
</xs:choice>
</xs:complexType>
and reference this type from the element declaration.
NB: this only works if there is no ambiguity, that is, if the validator can work out which branch of the choice to take based on the first element name that it sees in the instance document. If your choice were between two content models that both start with an h1 element, for example, you would have to reorganise the content models to remove the ambiguity.
I have the following Map that contains either Double or Integer instances as value, both of which extend the abstract class Number, annotated as follows:
#XmlElement(name="settings")
private Map<String,Number> settings;
It's marshalled into XML as:
<settings>
<entry>
<key>SETTING_A</key>
<value xsi:type="xs:double">0.03</value>
</entry>
<entry>
<key>SETTING_B</key>
<value xsi:type="xs:int">1000</value>
</entry>
</settings>
I also need to provide the XSD for this type of XML, and here is where I have problems. I tried to define a complexType with a choice, but doesn't work because the element that contain the int, and the element that contains the double can't have the same name (ie. they can't be both named "value"), which is exactly what the JAXB generated XML does.
The following XSD would work, but I don't want to have different element names ( or ):
<xsd:complexType name="Entry">
<xsd:sequence>
<xsd:element name="key" type="NimrodSettingKey" minOccurs="1" maxOccurs="1"/>
<xsd:choice>
<xsd:element name="double" type="xsd:double" minOccurs="1" maxOccurs="1"/>
<xsd:element name="int" type="xsd:integer" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
Any suggestions on how should I specify that the element could be an int or a double in my XSD document?
Thanks!
EDIT #1
#svasa suggested using the following approach in my XSD, which give the same name to an element inside a choice:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Settings"/>
<xsd:complexType name="Settings">
<xsd:sequence>
<xsd:element name="key" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:choice>
<xsd:element name="value" xs:type="xsi:double" minOccurs="1" maxOccurs="1" />
<xsd:element name="value" xs:type="xsi:integer" minOccurs="1" maxOccurs="1" />
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
but my XSD editor complained with this error:
complex type 'Settings' violates the unique particle attribution rule in its components 'value' and 'value'
which I think means that the two elements under the must have different names each, they can't both be named "value".
I finally opted for refactoring my code from:
#XmlElement(name="settings")
private Map<String,Number> settings
to:
#XmlElementWrapper(name="settings")
#XmlElement(name="setting")
private List<Setting> settings;
My Settings class was renamed to Setting and now stores one single setting with attributes:
#XmlAttribute(name="name")
private String name;
#XmlAttribute(name="intValue")
private Integer intValue;
#XmlAttribute(name="doubleValue")
private Double doubleValue;
And when marshalled into XML, it produces the elements that either have doubleValue or intValue attributes (but the element is named in both cases):
<settings>
<setting name="SETTING_A" doubleValue="1.0E-5"/>
<setting name="SETTING_B" intValue="1000"/>
...
</settings>
And the XML generated is valid when the XSD contains:
<xsd:complexType name="Settings">
<xsd:sequence>
<xsd:element name="setting" type="Setting" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Setting">
<xsd:attribute name="name" type="xsd:string"/>
<xsd:attribute name="doubleValue" type="xsd:double"/>
<xsd:attribute name="intValue" type="xsd:int"/>
</xsd:complexType>
The xs:choice should enable you to specify integer or double, and maxOccurs="1" will take care of only one value.
But if you want the key to be unique, you could use xsd:unique like below:
<xsd:element name="settings">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="entry">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="key" type="NimrodSettingKey" minOccurs="1" maxOccurs="1" />
<xsd:choice>
<xsd:element name="value" xsi:type="xsd:double" minOccurs="1" maxOccurs="1" />
<xsd:element name="value" xsi:type="xsd:integer" minOccurs="1" maxOccurs="1" />
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:unique name="keyU">
<xsd:selector xpath=".//key" />
<xsd:field xpath="." />
</xsd:unique>
</xsd:element>
This section :
<xsd:unique name="keyU">
<xsd:selector xpath=".//key" />
<xsd:field xpath="." />
</xsd:unique>
adds an unique constraint that specifies your keys should be unique.
The schema parser is able to parse the ComplexTypes of form:
<xsd:complexType name="PersonType">
<xsd:sequence>
<xsd:element name="id" type="xsd:string"/>
<xsd:element name="firstName" type="xsd:string" />
<xsd:element name="lastName" type="xsd:string" />
<xsd:element name="address" type="tns:AddressType"/>
</xsd:sequence>
</xsd:complexType>
But it is not able to parse the ComplexTypes of form:
<xsd:element name="PersonType">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="id" type="xsd:string"/>
<xsd:element name="firstName" type="xsd:string" />
<xsd:element name="lastName" type="xsd:string" />
<xsd:element name="address" type="tns:AddressType"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
In the later form it considers "PersonType" to be just an Element and not ComplexType. Hence the elements included in it are not parsed at all. Does anyone have a solution for this ?
I ran into the same problem today so I thought to see what SOAP-UI has to say about this when providing the wsdl file that has similar contents as the second image,
it showed them as Anonymous Complex Types yet have no solution for them, one thought can be to use the elements separately outside complexType tags.
Also anonymous types are not preferred. Probably the below link can help :
https://www.ibm.com/developerworks/library/ws-avoid-anonymous-types/ws-avoid-anonymous-types-pdf.pdf
I am trying to unmarshall the following XML using JAXB:
<Works>
<Work>
<Composers>
<Composer>
<Name>A name</Name>
</Composer>
<Composer>
<Name>A name 2</Name>
</Composer>
</Composers>
</Work>
</Works>
I have generated all of the classes using XJC. If I want to access the Composers collection, I have to do this:
List<Composer> composers = work.getComposers().getComposer();
Is there any way I can do the following instead?
List<Composer> composers = work.getComposers();
I appreciate the need for a Composers object as it derived from the XML, but when dealing in Java, having an intermediate POJO that stores the collections seems a bit redundant.
My XSD is:
<xsd:complexType name="Works">
<xsd:sequence>
<xsd:element name="Work" type="Work" maxOccurs="unbounded" minOccurs="0"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Work">
<xsd:sequence>
<xsd:element name="Composers" type="Composers"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Composers">
<xsd:sequence>
<xsd:element name="Composer" type="Composer" maxOccurs="unbounded" minOccurs="0"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Composer">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"></xsd:element>
</xsd:sequence>
</xsd:complexType>
The #XmlElementWrapper plugin does exactly what you want.
For anybody who can not or does not want to use the plugin:
If you can live with a different XML structure, it's possible to avoid generating the extra wrapper classes by simply using maxoccurs="unbounded" and leaving out the containing element. Using the original example:
<xsd:element name="Work" type="Work" maxOccurs="unbounded" minOccurs="0"/>
<xsd:complexType name="Work">
<xsd:sequence>
<xsd:element name="Composer" type="Composer" maxOccurs="unbounded" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Composer">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"></xsd:element>
</xsd:sequence>
</xsd:complexType>
will produce a structure like this:
<Work>
<Composer>
<Name>A name</Name>
</Composer>
<Composer>
<Name>A name 2</Name>
</Composer>
</Work>
This will put a method on the Work type that returns a List<Composer> object. Unfortunately the method is called getComposer instead of getComposers, but you can use annotations or custom bindings to fix that problem.