xpath to rename single class in crazy hierarchy - java

I'm trying to generate classes from wsdl using jaxws-maven-plugin, but I get uncompilable results. The problem is this part of one of the xsds, where you can see that there are nested elements with the same name:
<xs:complexType name="TrafficCountsReplyData" abstract="true">
<xs:sequence>
<xs:element name="effectiveTrafficWindow" type="common:DateTimeMinutePeriod" minOccurs="1" maxOccurs="1"/>
<xs:element name="flows" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="item" type="flow:Flow" minOccurs="0" maxOccurs="100"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="counts" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="item" minOccurs="0" maxOccurs="1440">
<xs:complexType>
<xs:sequence>
<xs:element name="key" type="common:DateTimeMinutePeriod" minOccurs="1"
maxOccurs="1"/>
<xs:element name="value" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="item" minOccurs="1" maxOccurs="3">
<xs:complexType>
<xs:sequence>
<xs:element name="key" type="flight:TrafficType"
minOccurs="1" maxOccurs="1"/>
<xs:element name="value" type="flow:Counts" minOccurs="1"
maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
As you can see, there there are multiple elements named item. This result in multiple inner classes with the same name inside of the single class TrafficCountsReplyData
So I'm trying to put together a binding file which would rename one of them. When I try to rename the outer item in the counts element using this:
<jaxb:bindings node="//xs:complexType[#name='TrafficCountsReplyData']//xs:element[#name='counts']//xs:element[#name='item']">
<jaxb:class name="Lulz"/>
</jaxb:bindings>
I get the following error:
[ERROR] XPath evaluation of "//xs:complexType[#name='TrafficCountsReplyData']//xs:element[#name='counts']//xs:element[#name='item']" results in too many (2) target nodes
When I create the binding xpath expression for the inner one like this:
<jaxb:bindings node="//xs:complexType[#name='TrafficCountsReplyData']//xs:element[#name='counts']//xs:element[#name='item']//xs:element[#name='value']//xs:element[#name='item']">
Then I get following error:
java.lang.IllegalArgumentException: Illegal class inheritance loop. Outer class Lulz may not subclass from inner class: Lulz
I can't figure out how to make this work. Where does the inheritance come from? There's another item in the flows element, but that shouldn't be matched by the Xpath. Without the binding file, I can generate the sources. I have correct schema in the binding file, because I can for example rename the class generated by the parent element.

mmm
I had a similar issue, but with properties..
I don't ahve the full xsd to check, but provided you want to change the OUTER item tag into something else, try this one:
<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="../yourlocation/yourschema.xsd" version="1.0">
<!-- Customise the package name -->
<jxb:schemaBindings>
<jxb:package name="whatyouwant.something"/>
</jxb:schemaBindings>
<!-- rename the value element -->
<jxb:bindings node="//xs:complexType[#name='TrafficCountsReplyData']//xs:sequence//xs:element[#name='counts']//xs:complexType//xs:sequence//xs:element[#name='item']">
<jaxb:class name="Lulz"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
If this seems not to work if you can disclose the xml I should be able to help you furthe (on vacation until monday in case) , but consider that you were giving the wrong "path", jumping away a few "subelement" in your xpath expression.
Let me know.

I've found the solution here: JAXB Customizations With a Poorly Formed WSDL
I had to add /xs:complexType at the end of the Xpath. I guess it's because the root of the class is in fact the complexType and not enclosing xs:element. So it was like this:
<jaxb:bindings node="//xs:complexType[#name='TrafficCountsReplyData']//xs:element[#name='counts']/xs:complexType/xs:sequence/xs:element[#name='item']/xs:complexType">
<jaxb:class name="Lulz"/>
</jaxb:bindings>
Now I can generate classes and compile them.

Related

isSet methods not generated using jaxb2-basics simplify plugin

I have a schema with two elements within a <xs:choice/> block, as per the following fragment:
<xs:complexType name="POCD_MT000040.Component2">
<xs:sequence>
<xs:element name="realmCode" type="CS" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="typeId" type="POCD_MT000040.InfrastructureRoot.typeId" minOccurs="0"/>
<xs:element name="templateId" type="II" minOccurs="0" maxOccurs="unbounded"/>
<xs:choice>
<xs:element name="nonXMLBody" type="POCD_MT000040.NonXMLBody"/>
<xs:element name="structuredBody" type="POCD_MT000040.StructuredBody"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="nullFlavor" type="NullFlavor" use="optional"/>
<xs:attribute name="typeCode" type="ActRelationshipHasComponent" use="optional" fixed="COMP"/>
<xs:attribute name="contextConductionInd" type="bl" use="optional" fixed="true"/>
</xs:complexType>
This is part of the HL7/CDA specification schemas, by the way.
Well, I am using maven-jaxb2-plugin to generate the Java classes, with a touch of the jaxb2-basics plugin to simplify complex elements, like nonXMLBody and structuredBody. Let's say I have a bindings file with the following contents:
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify"
jxb:extensionBindingPrefixes="xjc simplify"
version="2.1">
<jxb:globalBindings
typesafeEnumMaxMembers="1000"
generateMixedExtensions="true"
generateIsSetMethod="true"
choiceContentProperty="true">
<xjc:serializable uid="1" />
</jxb:globalBindings>
<jxb:bindings schemaLocation="xsd/POCD_MT000040.xsd">
<jxb:bindings node="xs:complexType[#name='POCD_MT000040.Component2']//xs:choice">
<simplify:as-element-property />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
The attributes are generated as expected:
protected POCDMT000040NonXMLBody nonXMLBody;
protected POCDMT000040StructuredBody structuredBody;
However, although I am using generateIsSetMethod="true" in the global bindings, the methods isSetNonXMLBody ( ) and isSetStructuredBody ( ) are not being generated at all. The equivalent methods for the rest of the attributes are present, though, like isSetTypeId ( ).
Am I missing any option I should know of to generate these methods in the aforementioned elements?

Converting Java generic object to XML using JAXB

I want to XML payloads like:
<ResponseDto>
<ResponseHeader>
<success>true</success>
</ResponseHeader>
<ResponseBody>
<ObjectA>
</ObjectA>
</ResponseBody>
</ResponseDto>
and another payload like:
<ResponseDto>
<ResponseHeader>
<success>true</success>
</ResponseHeader>
<ResponseBody>
<ObjectB>
</ObjectB>
</ResponseBody>
</ResponseDto>
so I want to make a class for ResponseDto which contains ResponseHeader Object and a generic Java Object in which I can place different types of objects, so I tried multiple types of Objects in a single class with #XMLElement(name = "ResponseBody") but it did not allow me to have same names of XMLElements
What can I do in this scenario?
Thanks in advance.
Most of enterprise applications use JAXB. You could get many tutorials some are below.
http://www.mkyong.com/java/jaxb-hello-world-example/
https://examples.javacodegeeks.com/core-java/xml/bind/jaxb-marshal-example/
https://www.javacodegeeks.com/2014/12/jaxb-tutorial-xml-binding.html
Step 1: First you would require to make xsd file. There are many online sites where xsd can be generated. Use http://xmlgrid.net/xml2xsd.html for now. XSD should look like this.
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ResponseDto">
<xs:complexType>
<xs:sequence>
<xs:element name="ResponseHeader">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="success"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ResponseBody">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="ObjectA" minOccurs="0"/>
<xs:element type="xs:string" name="ObjectB" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Refer my below post for reference.
read and get xml values in java

Shared class for child element in JAXB in different xmls/roots

In JAXB when using automatic class generation via xjc from xsd scheme.
alpha.xsd
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="alpha">
<xs:complexType>
<xs:sequence>
<xs:element name="persons">
<xs:complexType>
<xs:sequence>
<xs:element name="person" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
beta.xml
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="country">
<xs:complexType>
<xs:sequence>
<xs:element name="class">
<xs:complexType>
<xs:sequence>
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
As you can see there is Person element which is shared among these two schemes. What I would like to do is:
generate classes using xjc in a way that ObjectFactory class is shared for both schema classes (the output classes will be in one package)
not use nested static classes (with attribute localScoping="toplevel")
use Person class to bind with /alpha/persons/person as with /country/class/person so there are not two Person classes created
The purpose of this is unmarshalling one xml, applying business logic and creating another one as output where some elements (like Person) are same and shared for both xml files. The namespace will be the same for both files.
I would welcome if you can present me with complete .xjb bindings settings file. So far mine contains only:
<jxb:bindings version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jxb:extensionBindingPrefixes="xjc">
<jxb:globalBindings localScoping="toplevel"/>
</jxb:bindings>
And of course I get name collision error as I do not know how to set binding compiler to see Person as the same entity/element.
You can use an external binding file to indicate that during class generation we wish to use our existing class for the complex type called Document.
binding.xml
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="beta.xsd">
<jxb:bindings node="//xs:element[#name='person']/complexType">
<jxb:class ref="alpha.Person"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
XJC Call
xjc -b binding.xml beta.xsd
If namespace of person from A will be equals namespace person from B, that xjc has to generate the correct classes.

How to properly declare an extension within a schema?

In my schema file below, I have an element Stat which extends Entity. As far as I am aware, I follow w3's example, but when I go to parse the schema (and the xml that uses the schema) with through java's DocumentBuilderFactory and SchemaFactory I get this exception:
org.xml.sax.SAXParseException; systemId: file:/schema/characterschema.xsd;
src-resolve.4.2: Error resolving component 'cg:Entity'. It was detected that
'cg:Entity' is in namespace 'http://www.schemas.theliraeffect.com/chargen/entity',
but components from this namespace are not referenceable from schema document
'file:/home/andrew/QuasiWorkspace/CharacterGenerator/./schema/characterschema.xsd'.
If this is the incorrect namespace, perhaps the prefix of 'cg:Entity' needs
to be changed. If this is the correct namespace, then an appropriate 'import'
tag should be added to '/schema/characterschema.xsd'.
So, it seems that I cannot see my namespace within my schema. Do I need to import my schema into itself or am I completely misreading this exception? Could it be that I am declaring my schema incorrectly?
This is my schema for reference:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:cg="http://www.schemas.theliraeffect.com/chargen/entity"
elementFormDefault="qualified">
<xs:element name="Entity">
<xs:complexType>
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="description" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="Stat">
<xs:complexType>
<xs:complexContent>
<xs:extension base="cg:Entity">
<xs:sequence>
<xs:element name="table" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
There are two problems with your schema. First, you don't declare a targetNamespace so the Entity and Stat elements you are defining are not in a namespace. Second, a type can't extend an element, only another type.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:cg="http://www.schemas.theliraeffect.com/chargen/entity"
targetNamespace="http://www.schemas.theliraeffect.com/chargen/entity"
elementFormDefault="qualified">
<xs:complexType name="EntityType">
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="description" type="xs:string"/>
</xs:complexType>
<xs:element name="Entity" type="cg:EntityType" />
<xs:complexType name="StatType">
<xs:complexContent>
<xs:extension base="cg:EntityType">
<xs:sequence>
<xs:element name="table" type="xs:string" minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="Stat" type="cg:StatType" />
</xs:schema>
Here I'm defining two types, one of which extends the other, and two top level elements of the respective types. All the top-level types and elements are defined into the targetNamespace of the schema, and the nested table element inside StatType is also in this namespace because of the elementFormDefault="qualified" - without this the Entity and Stat elements would be in the http://www.schemas.theliraeffect.com/chargen/entity namespace but the table element would be in no namespace.

How to handle elements & attributes having same name in xsd while generating pojos using jaxb?

I have a xsd that contains something like:
<xs:complexType>
<xs:sequence minOccurs="0">
<xs:element ref="HereIsTheProblem"/>
<xs:element ref="blaBla"/>
</xs:sequence>
<xs:attribute name="something" type="xs:string" use="required">
<xs:annotation/>
</xs:attribute>
<xs:attribute name="somethingElse" type="xs:string">
<xs:annotation/>
</xs:attribute>
<xs:attribute name="HereIsTheProblem" type="xs:string">
<xs:annotation/>
</xs:attribute>
</xs:complexType>
now when i try to parse the schema using jaxb to generate java classes it fails:
[ERROR] Element "{http://something.somemorething.com/etc/}HereIsTheProblem" shows up in more than one properties.
how to resolve this without making any modification in the schema?
PS:my jaxb version is 2.1.13
You need to use a binding file indicating jaxB how it should handle this name collision. For example, put something like this in a file named something like bindings.xjb:
<jaxb:bindings version="2.1" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:com.fnf="http://www.fnf.com/xes">
<jaxb:bindings schemaLocation="your schema location here" node="/xs:schema">
<jaxb:bindings node="//XPath selector">
<jaxb:property name="HereIsTheProblem2" />
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Can't provide you a complete solution without a complete schema
Also we can modify the XSD as below.
<xs:complexType>
<xs:sequence minOccurs="0">
<xs:element ref="HereIsTheProblem"/>
<xs:element ref="blaBla"/>
</xs:sequence>
<xs:attribute name="something" type="xs:string" use="required">
<xs:annotation/>
</xs:attribute>
<xs:attribute name="somethingElse" type="xs:string">
<xs:annotation/>
</xs:attribute>
<xs:attribute name="HereIsTheProblem" type="xs:string">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="HereIsTheProblemAttr"/>
</xs:appinfo>
</xs:annotation>
</xs:attribute>
</xs:complexType>
The main issue is inside the pojo class, if we have the element and the attribute with the same name, it will try to create variables with the same name which is not allowed in simple java principles. So we can define the variable name to be different from one another like above.

Categories