When I run the following command:
xjc -b xmlSchema.xjb -d src -p com.q1labs.qa.xmlgenerator.model.generatedxmlclasses xmlSchema.xsd
It creates Java classes however I've found that my root class does not have the correct name and does not have #XmlRootElement which declares it as a root element which means when I use the classes to generate XML it is not formed properly.
XSD Schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified" targetNamespace="http://ibm.org/seleniumframework"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Test" type="sel:TestType" xmlns:sel="http://ibm.org/seleniumframework"/>
<xs:complexType name="TestType">
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element type="sel:Option1" name="Option1" xmlns:sel="http://ibm.org/seleniumframework"/>
<xs:element type="sel:Option2" name="Option2" xmlns:sel="http://ibm.org/seleniumframework"/>
<xs:element type="sel:Option3" name="Option3" xmlns:sel="http://ibm.org/seleniumframework"/>
</xs:choice>
</xs:complexType>
This is the output I am getting:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<testType xmlns="http://ibm.org/seleniumframework"/>
Generated classes correspond to complex types. Anonymous complex types that are declared as part of global elements will get an #XmlRootElement annotation. Others will have a #XmlElementDecl annotation generated on the ObjectFactory class. This is because there may be more than one global element that corresponds to the same complex type.
For More Information
http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html
Related
I have a WSDL that uses an xsd:any element in a return type for one of the methods, like this:
<xs:element name="Method_XMLResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Method_XMLResult">
<xs:complexType mixed="true">
<xs:sequence>
<xs:any/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
When I run the WSDL through the wsimport tool, I get a generated class that has this xs:any field mapped as a list of objects:
public static class MethodXMLResult {
#XmlMixed
#XmlAnyElement(lax = true)
protected List<Object> content;
}
When invoking the service using the generated code, I get instances of org.w3c.dom.Node in the content list (com.sun.org.apache.xerces.internal.dom.ElementNSImpl to be precise) that I would need to parse myself. I was, however, provided with a separate, external schema document for the objects actually returned - and I'm trying to somehow feed it to wsimport so it generates the classes for them as well.
I'm trying to accomplish that through JAX-WS / JAXB customization file like this:
<jaxws:bindings xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xmlns:a="http://www.w3.org/2001/XMLSchema"
wsdlLocation="wsdlLocation.wsdl">
<jaxws:bindings node="wsdl:definitions">
<jaxws:bindings node="wsdl:types" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
<jaxws:bindings node="//s:schema[#targetNamespace='wsNamespace']">
<jaxb:bindings node="//s:element[#name='Method_XMLResponse']//s:any">
...
</jaxb:bindings>
</jaxws:bindings>
</jaxws:bindings>
</jaxws:bindings>
</jaxws:bindings>
Looks like wsimport picks the right location to customize (gave me numerous error meesages with properly designated line number in the WSDL), but I can't figure out how to fill the <jaxb:bindings> element to make wsimport generate classes from the external schema. Is it even possible? Any help would be much appreciated.
I see you are use mixed type with xs:any in your XSD. I think it usefull custimization for a mixed type following JAXB adjust:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings generateMixedExtensions="true"/>
</jaxb:bindings>
You can add external JAXB binding files to wsimport whith -b parameter.
I think you can adjust xs:any with following ways:
Skip shema:
<xs:any processContents="skip" maxOccurs="unbounded" minOccurs="0" />
Skip binding:
#XmlAnyElement
public List<Element> getAny();
Strict schema:
<xs:any maxOccurs="unbounded" minOccurs="0" />
Strict binding:
#XmlAnyElement(lax=true)
public List<Object> getAny();
and:
with processContents=lax means any XML elements can be
placed here, but if their element names match those defined in the
schema, they have to be valid. XJC actually handles this exactly like
processContents='strict', since the strict binding allows unknown
elements anyway.
You can read more about in this link.
May be help this answer to accomplish your JAX-WS / JAXB customization file.
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"/>
I'm using JAXB on my project, but from time to time, I face some problems that I can't solve. I have setup my environment like this:
Armor Class
package com.fortresswars.entity.component;
#XmlType(name = "armor", namespace = "http://fortresswars.com")
public class ArmorComponent extends AbstractComponent
package-info.java
#XmlSchema(xmlns = #XmlNs(namespaceURI = "http://fortresswars.com", prefix = "fw"), elementFormDefault = XmlNsForm.UNQUALIFIED, namespace = "http://fortresswars.com")
package com.fortresswars.entity.component;
The generated schema header is almost correct:
<xs:schema elementFormDefault="unqualified" version="1.0" targetNamespace="http://fortresswars.com" xmlns:fw="http://fortresswars.com" xmlns:tns="http://fortresswars.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
The only thing I didn't like is that TNS prefix that JAXB puts there and I can't remove. I'm using an ant task (com.sun.tools.jxc.SchemaGenTask), and I remember reading somewhere that this was the problem.
The rest of the generated scheme follows below. I'll show only the relevant part about armor:
<xs:complexType name="armor">
<xs:complexContent>
<xs:extension base="tns:abstractComponent">
<xs:sequence>
<xs:element name="value" type="xs:short" minOccurs="0"/>
<xs:element name="type" type="tns:armor-type" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
And the element that is using the armor component:
<xs:complexType name="character">
<xs:complexContent>
<xs:extension base="tns:thing">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="armor" type="tns:armor"/>
<xs:element name="model" type="tns:model"/>
<xs:element name="status" type="tns:status"/>
<xs:element name="costs" type="tns:costs"/>
</xs:choice>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
To test this, I created a XML Document (see the TNS prefix, I need to put it, or the fw prefix, along with the xmlns:fw also).
<?xml version="1.0" encoding="UTF-8"?><tns:character xmlns:tns="http://fortresswars.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="/home/shirkit/jMonkeyProjects/Fortress Wars/Core/schema/full.xsd">
<armor>
<value>5</value>
<type>NORMAL</type>
</armor>
</tns:character>
But when I'm unmarshalling this document, here's the error I get:
Exception: unexpected element (uri:"", local:"armor"). Expected elements are <{http://fortresswars.com}armor>,<{http://fortresswars.com}attacks>,<{http://fortresswars.com}costs>,<{http://fortresswars.com}model>,<{http://fortresswars.com}abilities>,<{http://fortresswars.com}status>,<{http://fortresswars.com}movement>
I have setup elementFormDefault to UNQUALIFIED, and even though this doesn't work. Why I'm getting this exception? And can I remove TNS prefix from the generated schema?
when you define a namespace prefix for elements of http://fortresswars.com you need to prefix all elements with it, not only character. So this should work
<?xml version="1.0" encoding="UTF-8"?>
<tns:character
xmlns:tns="http://fortresswars.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="/home/shirkit/jMonkeyProjects/Fortress Wars/Core/schema/full.xsd">
<tns:armor>
<tns:value>5</tns:value>
<tns:type>NORMAL</tns:type>
</tns:armor>
</tns:character>
The tns prefix used in the schema is unrelated to what you use as prefix for XML text that you unmarshal. You may choose any other in xmlns:whatyoulike="http://fortresswars.com". The key that connects the elements in the XML document to the definitions in the schema file is the namespace URI, in your case "http://fortresswars.com". If you define your namespace as default namespace, you can omit the prefix on every element:
<?xml version="1.0" encoding="UTF-8"?>
<character
xmlns="http://fortresswars.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="/home/shirkit/jMonkeyProjects/Fortress Wars/Core/schema/full.xsd">
<armor>
<value>5</value>
<type>NORMAL</type>
</armor>
</character>
The namespace prefix in the XSD file helps to avoid name clashes if you wan't to use the schema file together with other schema files that define types or elements with the same name. It does not force you to use it in the xml files you want to unmarshal.
On the other hand, when you marhshal objects to XML, the file package-info.java defines what prefix JAXB uses, but this only works in recent versions of JAXB and it's not always easy to assure that the correct version is in use when your code runs. But you may use a NamespacePrefixMapper to control that.
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>
I have used the Jaxme 2 libraries before to generate Java code from .XSD files without a problem. I'm currently encountering a problem generating Java from an XSD file that contains a http://schemas.microsoft.com/2003/10/Serialization/ namespace.
Some sample code from my .XSD is:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/MyMessagingTypes"
xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
<xs:complexType name="MyMessage">
<xs:sequence>
...
<xs:element minOccurs="0" name="MyPlanID" type="ser:guid" />
...
</xs:sequence>
</xs:complexType>
<xs:element name="MyMessage" nillable="true" type="tns:MyMessage" />
</xs:schema>
The Error I'm getting is:
Invalid element: The type {http://schemas.microsoft.com/2003/10/Serialization/}guid is not defined.
Any ideas what the problem is or how I can generate Java code from this xsd?
I don't know where the schema for http://schemas.microsoft.com/2003/10/Serialization/ is located, but you would have to find it, and make sure that Java sees both schemas. Alternatively, you could edit the XSD to include your own GUID type instead.