Java/XSD parsing - java

I doubt if there is something like this but I thought to ask though:
Does anyone know if there is a library in Java that reads an xsd file and "creates" the defined elements e.g. in a String format to use in the code?
E.g. read in the following schema:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Address">
<xs:complexType>
<xs:sequence>
<xs:element name="Street" type="xs:string" />
<xs:element name="Town" type="xs:string" />
<xs:element name="Country" type="xs:string" minOccurs="0" />
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
And have a String in the following format:
<Address>
<Street></Street>
<Town></Town>
<Country></Country>
</Address>
Automatic tools do something similar, i.e. parse a WSDL and from the types section create for example JAXB classes that can be instances of the elements defined in schema.
Is there any library to do this?
UPDATE:
For example in Eclipse when creating an xml descriptor for a web application it presents a tree table with all the required elements for the users to fill in according to schema. How do they do it? I imagine they parse the xsds included in the jars
Any input is very welcome.
Thank you!

If its a WSDL file with which you want to generate Java classes, then Axis WSDL2Java (based on JAXB) can be used to get classes based on the schema defined in the WSDL.
JAXB also offers binding framework which you might want to look up.
http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/twbs_jaxbschema2java.html
Above link should be useful.

oXygen has an XML instance generator that can generate a set of XML document samples based on a given XML Schema.
You can also invoke it from the commandline.

Related

Can XSD Assertions be Used in Specifying a WSDL File

I have a WSDL file which also contains all types used in it (via <wsdl:types>
tag). When defining the types, I have something like this:
<wsdl:definitions name="service"
targetNamespace="http://www.xxx.yyy/reg/definitions" xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tax="http://www.xxx.yyy/reg/definitions" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
.............
<xs:complexType name="CompanyName">
<xs:sequence>
<xs:element name="Name" type="xs:string" />
<xs:element name="ShortName" type="xs:string" minOccurs="0" />
</xs:sequence>
<xs:attribute name="Language" type="tax:LanguageType" use="required"/>
<xs:assert test="ShortName or #Language != 'Language1'"/>
</xs:complexType>
.............
</wsdl:definitions>
Unfortunately, it doesn't work giving the following exception when I try to start the application on Tomcat:
javax.xml.ws.WebServiceException: org.xml.sax.SAXParseException; s4s-elt-invalid-content.1: The content of 'CompanyName' is invalid. Element 'assert' is invalid, misplaced, or occurs too often.
The WSDL version is 1.2 and I don't know which version of xsd it uses when types are described in it, so I don't know if it is a xsd version (1.0 vs. 1.1) issue or something else.
Can someone help me in finding the real issue?
EDIT: I have added the header of the wsdl.
I have added the version attribute (version="1.1") to <xs:schema>
definition but that didn't help either:
<xs:schema targetNamespace="http://www.xxx.yyy/reg/definitions" elementFormDefault="qualified" version="1.1">
Looks like assertions were introduced with XML Schema v1.1 when the XMLSchema definition moved over to w3.org.
Sample header:
<wsdl:description
targetNamespace="http://www.w3.org/2002/ws/sawsdl/spec/wsdl/order#"
xmlns="http://www.w3.org/2002/ws/sawsdl/spec/wsdl/order#"
xmlns:wsdl="http://www.w3.org/ns/wsdl"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:sawsdl="http://www.w3.org/ns/sawsdl">

SOAP without namespace in response (Spring Boot)

I'm following this example to build a web service with Soap. Is there a way to remove the targetNamespace for the Soap response? With SoapUI I get this response:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:getAllResponse xmlns:ns2="http://spring.io/guides/gs-producing-web-service">
<ns2:timestamp>12/18/2015 10:51:02 AM</ns2:timestamp>
<ns2:MyItem>
<ns2:class>myClass</ns2:class>
<ns2:name>MyItemName</ns2:name>
</ns2:MyItem>
</ns2:getAllResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And would like to get it without the target namespace, e.g. like:
...
<MyItem>
<MyItem>
<class>myClass</class>
<name>MyItemName</name>
</MyItem>
I'm sending an empty request to get a list of MyItems. My xsd looks like this:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:tns="http://spring.io/guides/gs-producing-web-service"
targetNamespace="http://spring.io/guides/gs-producing-web-service">
<xs:element name="getAllRequest">
<xs:complexType>
<xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getAllResponse">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="1" name="timestamp" type="xs:string"/>
<xs:element maxOccurs="unbounded" name="MyItem" type="tns:MyItem"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="MyItem">
<xs:sequence>
<xs:element name="class" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
The MyItem class will be generated automatically and gets annotated with this:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "MyItem", propOrder = {
"class",
"name",
})
public class MyItem { //....
Is there any way to get a response without the target namespace? I know its purpose and that it's actually quite useful. But it happened that it can't be processed any further by another tool with this target namespace and looks like this:
<MyItem xmlns="http://spring.io/guides/gs-producing-web-service"> ...
Thanks in advance!
Is there any way to get a response without the target namespace?
I hope not. A SOAP web service should have a well-defined, published interface and every response that it sends should conform to that interface. Usually, the interface is described by a WSDL document.
And would like to get it without the target namespace
<MyItem>
<class>myClass</class>
<name>MyItemName</name>
</MyItem>
Being pedantic, but the absence of a namespace prefix does not mean that there is no namespace. There might be a default namespace in force. So you could achieve XML that looks exactly like the above and the MyItem, class and name tags might still have a non-empty namespace.
I know its purpose and that it's actually quite useful.
The purpose of a namespace in an XML document ( whether a web service response, or any other XML ) is to avoid polluting the global namespace. Do you really want 'name' and 'class' to have exactly one meaning in your applications? Or would it be better if each schema could define its own version of those?
But it happened that it can't be processed any further by another tool with this target namespace and looks like this:
<MyItem xmlns="http://spring.io/guides/gs-producing-web-service"> ...
That looks like valid XML, so what's the problem? Is that output produced by the 'other tool'? Or is it something that the 'other tool' cannot handle?
Here is the simple and easiest solution for that problem. Create Package-Info.Java file in your model package and add the below script to that.
#javax.xml.bind.annotation.XmlSchema(namespace = "http://spring.io/guides/gs-producing-web-service", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = { #javax.xml.bind.annotation.XmlNs(namespaceURI = "http://spring.io/guides/gs-producing-web-service", prefix = "") })
package my.com.scicom.stars.model;
And add elementFormDefault as "qualified" in your xsd or wsdl file.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://spring.io/guides/gs-producing-web-service"
targetNamespace="http://spring.io/guides/gs-producing-web-service"
elementFormDefault="qualified">

JAXB support for SOAP style arrayType

I'm trying to make a new version of a server that previously used Axis 1.4 to respond to SOAP RPC requests using Spring-WS. I have a few of the RPC calls working, but I'm stuck trying to satisfy a request that expects a SOAP body that looks like this:
<rpcCallResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<responseElement soapenc:arrayType="xsd:string[5]"
xsi:type="soapenc:Array"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<responseElement xsi:type="xsd:string">val1</responseElement>
<responseElement xsi:type="xsd:string">val2</responseElement>
<responseElement xsi:type="xsd:string">val3</responseElement>
<responseElement xsi:type="xsd:string" xsi:nil="true"/>
<responseElement xsi:type="xsd:string" xsi:nil="true"/>
</responseElement>
</rpcCallResponse>
I'm struggling to write the XML schema for this, and to get the JAXB marshaller to shove the xsi:type annotations into the response.
What's the correct XML schema to use/set of annotations to use to get this to marhsal (Java -> XML) correctly?
One solution I found that works for getting the arrayType added is to, instead of deriving from the http://schemas.xmlsoap.org/soap/encoding/ schema, use a custom schema of the form:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.xmlsoap.org/soap/encoding/"
elementFormDefault="qualified">
<xs:attribute name="arrayType" type="xs:QName" />
</xs:schema>
...which replaces the type of the arrayType attribute with an xs:QName (vs. the actual type, which is just an xs:string). The advantage of using a QName seems to be that JAXB will take the QName's namespace and shove it onto the element when serialization happens -- which was the main blocker on getting a working schema above.
The schema for above now looks something like:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:encoding="http://schemas.xmlsoap.org/soap/encoding/"
targetNamespace="http://foo.com/bar"
elementFormDefault="qualified">
<xs:import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="soapenc.xsd" />
<xs:element name="rpcCallResponse">
<xs:complexType>
<xs:element name="responseElement">
<xs:complexType>
<xs:sequence>
<xs:element name="responseElement" maxOccurs="5" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:attribute ref="soapenc:arrayType" />
</xs:complexType>
</xs:element>
</xs:schema>

How to maintain package structure when using schemagen and xjc

I am new to JAX B. I created a project with the structure :
src-
entity-
Person
property-
Address
I generate a xsd document using the command
C:\workspace\JAXTest\src>schemagen entity\Person.java property\Address.java
I see schema1.xsd in src folder now but it does not have any package information. So, If I use xjc to generate classes, I get all the classes in the same folder.
C:\workspace\JAXTest\src>xjc schema1.xsd
parsing a schema...
compiling a schema...
generated\Address.java
generated\ObjectFactory.java
generated\Person.java
What can be done so that the xsd can contain the package information so that the generated classes follow the structure of the classes used to create the xsd.
Thanks in advance!
Edit :
There is no particular requirement I am working towards. I am just trying to learn XSD-Class and Class-XSD conversions correctly. Also, I have found that I can use jax customization to specify the global package name but it doesn't work for individual classes. Basically, this does not put my Person in PersonPackage package.
<xs:complexType name="person">
<xs:annotation>
<xs:appinfo>
<jaxb:package name="PersonPackage"/>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:element name="address" type="address" minOccurs="0">
</xs:element>
<xs:element name="name" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>

Xml schema interfaces

I'm attempting to write an XML schema to define some model classes to be used in jaxb in java.
I would like to be able to define an interface in the xsd but I've no idea how to do this.
For example a lot of my classes will have an attribute called id which is type xs:ID. They will have an attribute called ref which is type xs:IDREF and they will have an attribute called extRef which means that there is a refrence but the element is not specified in the given xml file.
Ideally this would be an interface when converted to java for two reasons.
The classes that implement this are not necessarily connected.
I would like to specify a different inheritance tree for some of these objects.
Example:
<!-- Utility type to be externally referenceable this is too keep all the
externally refrencable attributes in check -->
<xs:complexType name="ExternallyReferenceable" abstract="true">
<xs:attribute name="extRef" type="externalReference" />
<xs:attribute name="id" type="xs:ID" />
<xs:attribute name="ref" type="xs:IDREF" />
</xs:complexType>
<xs:complexType name="ExternalCarPart">
<xs:extension base ="ExternallyReferenceable" />
</xs:complexType>
<xs:complexType name="CarPart">
<xs:extension base ="ExternalCarPart">
<xs:sequence>
<xs:element type="xs:string" name="partName" />
</xs:sequence>
</xs:extension>
</xs:complexType>
<xs:complexType name="CarLamp">
<xs:extension base ="ExternalCarPart">
<xs:sequence>
<xs:element type="xs:string" name="glassPurity" />
</xs:sequence>
</xs:extension>
</xs:complexType>
So in the above example it would be better if exteranllyRefrencable was an interface, and if carpart was an interface.
This would allow CarLamp to inherit from lamp rather than external car part. BicycleLamp could also implement the externallyRefrencable interface and extend lamp also.
Please ask me for clarification if the question isn't clear.
IIRC, JAXB doesn't generate interfaces from XSD.
JAXB also supports generating XSD from Java classes. I'm not sure what it does with interfaces in that regard, but perhaps you need to go at it in the opposite direction - begin with Java and generate XSD, though I'm not sure that will help you.

Categories

Resources