Retrieve the parent component of an XSComponent in XSOM - java

I'm using the XSOM framework to parse a batch of XSD files, and then write them into a graph db.
For every XSDeclaration, there is a possibility to check whether or not they are local, or global. In other words, whether a component is declared in the root of the XSD files, or if it's part of an anonymous type.
I would like to be able to retrieve the global parent, of which the local component is a part of but I could not find such a method anywhere in the java doc.
For example:
<xs:group name="group">
<xs:sequence>
<xs:element name="grEl1" type="xs:string" />
<xs:element name="grEl2" type="xs:string" />
<xs:element name="grEl3" type="xs:string" />
</xs:sequence>
</xs:group>
When I have the XSElementDecl with name grEl1, I check if it's local which will return true. I would then like to be able to ask that XSElementDecl in some way, to give me it's parent, which is the XSModelGroupDecl with name group.
Thanks in advance :)

Related

XML Validation against XSD : cvc-complex-type.2.4.a

Currently I am using javax.xml.validation.Validator to validate xml against given xsd. I have set custom error handler to get all exceptions instead of exiting at the first exception.
Sample xsd:
<xs:element type="xs:string" name="att1"/>
<xs:element type="xs:string" name="att2"/>
<xs:element type="xs:string" name="att3"/>
<xs:element type="xs:string" name="att4"/>
In xml if att2 and att3 values are not there, I am getting below exception.
cvc-complex-type.2.4.a: Invalid content was found starting with element 'att4'. One of '{"https://******":att2}' is expected.
But I need exception to be like this i.e. both att2 and att3 should be shown in expected list.
cvc-complex-type.2.4.a: Invalid content was found starting with element 'att4'. One of '{"https://******":att2, "https://******":att3}' is expected.
How can I achieve this?
As a second element, the xsd specifies att2, put you provided att4.
As a third element, the xsd specifies att3 but you didn't provide any element.
You can try to set the elements att2 and/or att3 as optional with :
minOccurs="0" maxOccurs="1"
If it doesn't work, you can try :
<xs:element type="xs:string" name="att1"/>
<xs:choice minOccurs="0" maxOccurs="2">
<xs:sequence>
<xs:element maxOccurs="1" name="att2" type="xs:string" />
<xs:element maxOccurs="1" name="att3" type="xs:string" />
</xs:sequence>
</xs:choice>
<xs:element type="xs:string" name="att4"/>
The validator is implemented as a finite state machine. It computes the permitted transitions from one state to another. After reading an att1 element, the only permitted transition is to an att2, and that's what it's telling you. It's not smart enough to explore the entire finite state machine and work out that at att4 would be valid if there was an att2 and then an att3.
The Saxon validator does a little better than this, but only a little: it won't give you what you're looking for here.
If it's any consolation, XSD validators generally do a lot better than regex engines (which is essentially what they are); regex engines generally just tell you that the input isn't matched by the regex, and give you no clue why.

How to resolve already defined elements in WSDL?

I'm trying to connect to a C#/NET (*.svc) webservice. I have to use java, thus wsdl2java is my choice.
Problem: somehow the targeting webservice defines lots of elements dublicate. This might be due to the nature of C# or whatever.
There are like 100+ elements as follows:
<xs:complexType name="Ticket">
<xs:sequence>
<xs:element minOccurs="0" name="ASegment"
nillable="true" type="tns:AnArray" />
</xs:sequence>
</xs:complexType>
<xs:element name="Ticket" nillable="true" type="tns:Ticket" />
Resulting in:
'Ticket' is already defined (org.apache.cxf:cxf-codegen-plugin:3.0.1:wsdl2java:generate-sources:generate-sources)
How can I cope with this? I read about a jaxb-binding.xml file, where I can "rename" specific elements explicit.
But if I apply this for 100+ elements, well the week has only 5 days...
Is there any way I can though auto generate the classes?
Please see this answer:
Prefixing JAXB generated classes
jaxb:nameXmlTransform is your friend.
I normally do <jaxb:elementName suffix="Element"/>.

Replicate REST API with SOAP

I have a simple REST api which sends data in JSON such as this:
http://myapp/color (POST w/ data in JSON) - Creates a new color in DB
http://myapp/color/id (GET) - Fetches details for a color from DB
http://myapp/color (GET) - Fetches details for all colors in DB
I would like to create a SOAP API for these three functions as well. So I'm going with Spring-WS.
I've created the SOAP API for the creation. With the following XSD
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:hr="http://www.myveryimportantcompany.com/tr/schemas"
targetNamespace="http://www.myveryimportantcompany.com/tr/schemas"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="ColorRequest">
<xs:complexType>
<xs:all>
<xs:element name="Color" type="hr:ColorType"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:complexType name="ColorType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="ColorResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="status" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I've also written functional test for the above which works fine.
Questions - I've never created a SOAP WS in the past so please ignore if questions are stupid.
How would the XSD look like for the remaining two functions?
Do I need a separate XSD for each function?
Can I test the SOAP service with a GUI as well? I gave SOAP GUI a show but it needs a WSDL. How can I create that?
PS: I'm using Spring-WS plugin from grails.
This is a kind of a subjective question I bet. I will try to answer as much elaborated as I can to make it useful. Bear with me. :)
First Thing First:-
SpringWS plugin uses contract-first webservice. The schema which you have created here should be a contract for the underlying webservice.
Each of the webservice should have its own contract which means its own schema.
SpringWS follows a convention of creating an Endpoint with the name same as the name of the contract schema.
You can use inheritance in the endpoints which will help you create a single xsd schema for all the contracts. In that case you have to inherit the parent endpoint in the corresponding child endpoints.
Example:-
For everyone's convenience lets use a User service instead of Color.
//Domain:-
class User{
String name
String email
Integer age
}
I would prepare a base schema for this entity, some what similar to what you did earlier for Color:
<!-- User.xsd -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:hr="http://www.myveryimportantcompany.com/tr/schemas"
targetNamespace="http://www.myveryimportantcompany.com/tr/schemas"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="UserType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="email" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
<xs:element name="User" type="hr:UserType"/>
</xs:schema>
Now come to each contract for each Service:-
<!-- GetUserService.xsd -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:hr="http://www.myveryimportantcompany.com/tr/schemas"
targetNamespace="http://www.myveryimportantcompany.com/tr/schemas"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="GetUserRequest" type="hr:GetUserRequestType"/>
<xs:complexType name="GetUserRequestType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="GetUserResponse" type="hr:GetUserResponseType"/>
<xs:complexType name="GetUserRequestType">
<xs:sequence>
<xs:element ref="hr:User"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Similarly you can have UpdateUserService.xsd doing the update [POST, PUT] piece.
Alternatively, you can accumulate all the xsds to a single contract named UserServices.xsd
Caveat
In case you have only one xsd for all service then you have to create a parent endpoint named (exactly same) as UserServicesEndpoint.groovy (see springws docs how to create endpoints), then your services endpoint would belike
class GetUserServiceEndpoint extends UserServicesEndpoint{....}
class UpdateUserServiceEndpoint extends UserServicesEndpoint{....}
In case you have all xsds separate, you do not need the inheritance.
Answers to Questions:
How would the XSD look like for the remaining two functions?
By now you know how should it look. The names should be something like UpdateColorService.xsd, GetColorService.xsd, GetAllColorsService.xsd
Do I need a separate XSD for each function?
Follow above. You can have separate or you can have them in one parent xsd. In that case, there has to be a parent endpoint as well.
Can I test the SOAP service with a GUI as well? I gave SOAP GUI a show but it needs a WSDL. How can I create that?
Yes you can. The best tool I found is SoapUI (free version is sufficient for me). You can also use Apache JMeter, if you are comfortable with it. Contract-first services always need a WSDL to run. As part of SpringWS plugin, you have a splendid DSL support which creates a WSDL for you after you run the application. Follow the docs again. I can explain that in a different question, because this answer has become an epic by now.
Words of Advice:
Finally, why do you need a SOAP Service when the whole world is RESTing in peace? :)
springws plugin is almost obsolete and has not been supported for years. I have customized the plugin to my need and have not submitted it to Grails PLugins yet. Did not feel like? But I think I have to now, since #Anthony is using it. :)
The plugin has jars inside project's lib directory which may clash with your dependencies.
Plugin uses old version of spring-ws-core which is definitely going to crash with spring-core:3.1.2 which comes with Grails 2.2.x.
You might get compilation errors with newer version of JDK (7 or above).

JAXB case sensitive class generation

I want to create classes from a standard schema learning object model. The schema appears to be broken due to a lowercased type. Is there any way that I can generate classes with jaxb in a "case insensitve" mode?
Here is the problem where the conflict comes out:
<xs:complexType name="Duration">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="duration" type="DurationValue"/>
<xs:element name="description" type="description"/>
<xs:group ref="ex:customElements"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="duration">
<xs:complexContent>
<xs:extension base="Duration">
<xs:attributeGroup ref="ag:duration"/>
<xs:attributeGroup ref="ex:customAttributes"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
I have rename the "duration" tag to "customDuration" and I have change the references as well and it works.
Thank you!
I think that you should change the schema in order to have Duration and duration_, generate JAXB objects and then change your JAXB classes generated in order to adapt them to the origina WSDL. For example, in Java:
#XmlElement(name = "Duration")
protected String duration;
#XmlElement(name = "duration")
protected String duration_;
(I have simplified the types in the example). Hope anyway you find a better solution.
This was already answered but Hope this will help some one else , use -XautoNameResolution so that new classes will be generated whenever it encounters two elements with same name (Case insensitive). I used it as following
xjc -d src -p com.sample -wsdl somewsdl.wsdl -XautoNameResolution

Convert XSD to tree structure with Java

I want to generate documentation for XML schemas.
My goal is to analyze the xsd file and to display it as a tree structure (with all complex / anonymous types resolved). Furthermore I need to annotate all items in that tree with their cardinality (as defined by the schema).
The following small example might help to clarify my problem.
a) the xsd file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="client" type="clientType" />
<xs:complexType name="clientType">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="first_name"/>
<xs:element name="last_name"/>
<xs:element name="address" type="addressType"
minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="addressType">
<xs:sequence>
<xs:element name="street"/>
<xs:element name="number" minOccurs="0" maxOccurs="1"/>
<xs:element name="city"/>
<xs:element name="zipcode"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
b) Output I'd like to see:
client [1]
first_name [1]
last_name [1]
address [1..n]
street [1]
number [0..1]
city [1]
zipcode [1]
Does anybody know a java based solution for this problem? Preferably based on Eclipse Schema Infoset, but I'm happy to use other libraries as well.
XSOM can normalize an XSD into a comprehensible data structure that you can loop over and print out.
Given that XSD schema are also XML you could process this as XML giving you many options for how to do this.
My preference would be to use an XSLT stylesheet with templates to match the element and complex type elements to get the output list, and further templates to match the minOccurs and maxOccurs attributes to get your cardinality.
Examples of stylsheets to do this are probably available online already.
Although not having a proper solution I would propose the following: use a tool that is capable of generating a sample XML instance based on the XSD, e.g. eclipse IDE (as it is open source it should be possible to extract the relevant code and use it within a standalone solution). This XML should be very close to the tree structure you are requiring. Then, parse the XSD and annotate the elements in the generated XML structure with the cardinalities.

Categories

Resources