Generating JAXB class from XSDs with similar attribute names - java

I use maven-jaxb2-plugin to generate jaxb annotated classes from xsd. I have many xsd files like those:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="A3">
<xs:complexType>
<xs:sequence>
<xs:element name="loginPartner">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="login"/>
<xs:element type="xs:string" name="password"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="A3">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="errorCode"/>
<xs:element type="xs:string" name="errorDescription"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
When I run maven plugin it gives me an error:
[ERROR] Error while parsing schema(s).Location [
file:schema1.xsd{10,16}]. org.xml.sax.SAXParseException: 'A3' is already
defined
Is there any way to fix this?
Actually I have many XSDs representing request/response messages to/from server. I want to simplify creating, validating, parsing messages. Maybe is there another solution for this?

I had a similar problem; I had two separate and independent WSDL (each with several schema definitions in each) that I was running through JAXB (via the maven-jaxb2-plugin) to generate mapping classes.
My WSDL's shared a duplicate schema definition that was causing XJC to choke.
Because they were both independent, I was able to generate JAXB mappings by running two separate executions of the maven-jaxb2-plugin - one for each WSDL (covered here - How can I tell jaxb / Maven to generate multiple schema packages?).

You cannot have conflicting element definitions within the same namespace. This is same as not allowing multiple classes with the same name in a given package in Java. Your best bet is to define them with different names or in different namespaces.

you can rename the second or the first A3 of your xsd in your jaxb binding file
<jaxb:bindings schemaLocation="filePath.xsd" node="/xs:schema">
<jaxb:bindings node="//xs:element[#name='A3']">
<jaxb:property name="SecondA3"/>
</jaxb:bindings>
</jaxb:bindings>

Related

Create XML on JAVA

I need to create an XML on JAVA but for multi fields on one element:
<cities>
<city_insert city_id="123" city_name="São Paulo" />
<city_insert city_id="456" city_name="Rio de Janeiro"/>
</cities>
As you can see on the example above, the element city_insert need to have city_id, and city_name , one element can have multiples fields.
How this can be done on Java?
I've searched for DOM and JDOM parsers but still don't know how this works.
Thank you!
Refer to this question for creating an XML using DOM parser.
Create XML file using java
In order to create an attribute (which you mentioned as fields), call setAttribute() method.
nodelist = doc.getElementsByTagName("city_insert");
for (Element element : nodelist) {
Element parent = element.getParentNode()
parent.setAttribute("city_id", "123");
parent.setAttribute("city_name", "São Paulo");
}
I allways do this things using jaxb
First, generate an xsd from your xml (there are many free online generators on the net)
For your xml, an online generated xsd look as follows:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="cities">
<xs:complexType>
<xs:sequence>
<xs:element name="city_insert" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="city_id" use="optional"/>
<xs:attribute type="xs:string" name="city_name" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Then, using jaxb (many IDE's like Eclipse have an easy way of doing it) generate jaxb classes from an xsd:
Click finish, then this is java console output:
parsing a schema...
compiling a schema...
com\erax\xml\test\xsd\Cities.java
com\erax\xml\test\xsd\ObjectFactory.java
And the generated classes:
Then just use jaxb marshalling to serialize and deserialize

nested xsd: Cannot resolve the name ... to a type defintion component

My webservice should be able to validate xml-input against a schema(request.xsd). The complextyped only element in the schema owns different subelements of types which are defined in other xsds. I am importing all thess xsds. At the end however element type cannot be resolved.
this ist my "request.xsd":
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fe="http://www.some.dir/featurenamespace"
xmlns="http://this.is.my.space"
targetNamespace="http://this.is.my.space"
elementFormDefault="qualified">
<xs:import schemaLocation=" http://www.some.dir/featurenamespace/cmplxtypes.xsd "
namespace=" http://www.some.dir/featurenamespace"/>
<xs:element name="elem1" type="request"/>
<xs:complexType name="request">
<xs:complexContent>
<xs:extension base="fe:complexElement">
<xs:sequence>
<xs:element name="record" type="fe:complexElement "/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
This is the schema (e.g. cmplxtypes.xsd) where the type 'complexElement' is defined:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fe="http://www.some.dir/featurenamespace"
xmlns:ofe ="http://www.some.dir/otherfeaturenamespace"
targetNamespace="http://www.some.dir/featurenamespace"
version="1.1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:include schemaLocation="fe_types.xsd" />
<xs:import schemaLocation="ofe_types.xsd" namespace="http://www.some.dir/otherfeaturenamespace"/>
<xs:complexType name="complexElement">
<xs:sequence>
<xs:element name="feature" type="fe:FeatureType "/>
<xs:element name="otherfeature" type="ofe:otherFeatureType"/>
</sequence>
</xs:complexType>
The files: cmplxtypes.xsd, fe_types.xsd and ofe_types.xsd share the same namespace.
Now, trying to validate myxml against request.xsd I get: cannot resolve 'complexElement' to a 'type defintion' component.
I do appreciate any help.
There are several inconsistencies in the schemas that may explain the error.
request.xsd doesn't appear to be importing cmplxtypes.xsd, where fe:complexElement is defined.
<xs:import
schemaLocation="http://www.some.dir/featurenamespace/cmplxtypes.xsd"
namespace=" http://www.some.dir/featurenamespace" />
cmplxtypes.xsd includes ofe_types.xsd even though the namespace does not match according to the import in request.xsd. Namespaces much match when including other schemas (or the included schema must have no target namespace).

JaxB xjc generated pojos contains blank namespaces

I'm using xjc from the command line to generate POJOs from an XSD. Here's the command I run:
"%java_home%\bin\xjc" -p com.etc.etc.etc.etc ConsolidatedAlert.xsd
For some of the POJOs generated, the properties in the POJO come back like the following:
#XmlElement(name = "UnparsedTelephone", namespace="")
protected String unparsedTelephone;
As far as I can tell, I don't specify these elements any differently than others that don't have the "namespace" attribute.
Here's the relevant sections of the XSD:
Type declaration:
<xs:complexType name="TelephoneType">
<xs:choice>
<xs:element name="UnparsedTelephone" type="xs:string"/>
<xs:element name="ParsedTelephone" type="ParsedTelephoneType"/>
</xs:choice>
</xs:complexType>
Element declaration:
<xs:element name="Telephone" type="TelephoneType"/>
Where "Telephone" is used:
<xs:complexType name="CompanyContactType">
<xs:sequence>
<xs:element ref="Telephone"/>
</xs:sequence>
</xs:complexType>
Where "CompanyContact" is used:
<xs:complexType name="AmountType">
<xs:sequence>
<xs:element ref="CompanyContact" minOccurs="0" />
<xs:element name="TriggerAmount" type="xs:string"/>
</xs:sequence>
</xs:complexType>
I can simply remove the namespace="" from each POJO, but that can take a bit, and I'd like a better understanding about why it's happening in the first place.
Also, this is about 8 XSDs all linked together. They all have the same targetNamespace and xmlns in the schema definition, but some of them have elementFormDefault="unqualified" and others have elementFormDefault="qualified". Could this be the cause of the problem?
Any ideas?
Namespace Qualification & XML Schema
When elementFormDefault="qualified" all the elements corresponding to this XML Schema will be namespace qualified. When elementFormDefault="unqualified" only global (top level) elements will be namespace qualified.
Namespace Qualification & JAXB
JAXB allows the namespace qualification to be set at the package level using #XmlSchema. Since you have multiple schemas and an undisclosed number of generated packages it's very possible XJC generated "" for namespace to override the default qualification to match the schema rules.

Ugly java code with xsd:sequence

I use JAXB to bind XSD schemas to POCOs. I have tried two different ways to write an XSD schema but each has a flaw:
Option 1
Problem: Each element is represented with <Elements> in XML instead of <Element>, plus they are not inside a container such as <ElementsContainer>.
XSD Schema
<xs:element name="Root" type="RootType" />
<xs:complexType name="RootType" />
<xs:sequence>
<xs:element name="Elements" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
Java
RootType r = new RootType();
r.getElements.add("Str1");
r.getElements.add("Str2");
Marshaled XML
<Root>
<Elements>Str1</Elements>
<Elements>Str2</Elements>
</Root>
Option 2
Problem: Java code looks uglier.
XSD Schema
<xs:element name="Root" type="RootType" />
<xs:complexType name="RootType" />
<xs:element name="Elements">
<xs:complexType>
<xs:sequence>
<xs:element name="Element" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:complexType>
Java
RootType r = new RootType();
r.getElements().getElement().add("Str1");
r.getElements().getElement().add("Str2");
Marshaled XML
<Root>
<Elements>
<Element>Str1</Element>
<Element>Str2</Element>
</Elements>
</Root>
Question: Is there a way to write a schema that outputs an XML like in Option 2 and whose code is written like in Option 1?
Edit: <xs:list> is not an option as elements may have white-spaces.
Starting from Java Classes
If you are starting from Java Objects you can use the #XmlElementWrapper annotation to add a grouping element.
#XmlElementWrapper(name="Elements")
#XmlElement(name="Element)
public List<Element> getElements() {
return elements;
}
Starting from XML Schemas
The XJC tool is very extensible. The following plug-in written for the XJC tool appears to allow you to generate #XmlElementWrapper annotations into your model.
https://github.com/dmak/jaxb-xew-plugin

referencing/including xsd files in a jar

I want to add an xsd file to our project that relies on types defined in another xsd that is in a jar. We use jaxb to generate Java classes from the xsds.
How do i refer to SchemaContainingFooTypeIsInaJAR.xsd so that 'FooType' resolves correctly and the proper Java classes get generated
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="SchemaContainingFooTypeIsInaJAR.xsd"/>
<xs:complexType name="FooMoreType">
<xs:complexContent>
<xs:extension base="FooType">
<xs:sequence>
<xs:element name="something" type="xs:boolean" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">
something something
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
You might be interested in these features:
http://confluence.highsource.org/display/MJIIP/User+Guide#UserGuide-CompilingaschemafromaMavenartifact
http://confluence.highsource.org/display/MJIIP/User+Guide#UserGuide-Usingcatalogs
In short, you can write a catalog file which would point to your schema in a JAR file:
REWRITE_SYSTEM "some/url/a.xsd" "maven:org.jvnet.jaxb2.maven2:maven-jaxb2-plugin-tests-episodes-a!/a.xsd"
DISCLAIMER: I am the principal dev of maven-jaxb2-plugin.
See XML Schema reference and JAXB SchemaFactory source order must follow import order between schemas?
The consensus appears to be: you need to supply your own resolver.
Replace your line:
<xs:include schemaLocation="SchemaContainingFooTypeIsInaJAR.xsd"/>
with
<xs:include schemaLocation="jar:file:///path/to/jar/thing.jar!/path/inside/jar/to/file.xsd"/>

Categories