XSD Date with attribute but optional value - java

How do I an XSD date value which is optional? Is there a way I could escape from using nillable?
For instance, both
<element attribute="attribute">optional-value</element>
<element attribute="attribute"/>
are valid types, where "optional-value" must be defined as an xsd:date type.

Yes, but not with something that tools like:
XSD:
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="EmptyDate">
<xsd:attribute name="attribute" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="EmptyDate">
<xsd:union memberTypes="xsd:date emptyString"/>
</xsd:simpleType>
<xsd:simpleType name="emptyString">
<xsd:restriction base="xsd:string">
<xsd:length value="0"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Invalid XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attribute="attribute1" xmlns="http://tempuri.org/XMLSchema.xsd"> </root>
Valid XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attribute="attribute1" xmlns="http://tempuri.org/XMLSchema.xsd"/>

Related

Importing XSD schema into multiple XSDs generates identical classes, one per package

I have a XSD service_errormessage_v1.0.xsd with some generic error messages I want to use in multiple places:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.mycompany.com/service/errormessage/v1.0"
xmlns:em="http://www.mycompany.com/service/errormessage/v1.0"
version="1.0" elementFormDefault="qualified">
<xsd:complexType name="ErrormessageType">
<xsd:annotation>
<xsd:documentation>
Describes an error.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="errorcode" type="em:errorcodeType"/>
<xsd:element name="errormessage" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="errorcodeType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="error_a"/>
<xsd:enumeration value="error_b"/>
<xsd:enumeration value="error_c"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Now, I'm importing it in multiple other XSDs:
myserviceA.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.mycompany.com/service/myserviceA/v1.0"
xmlns:em="http://www.mycompany.com/service/errormessage/v1.0"
xmlns:tns="http://www.mycompany.com/service/myserviceA/v1.0"
elementFormDefault="qualified">
<xsd:import namespace="http://www.mycompany.com/service/errormessage/v1.0"
schemaLocation="service_errormessage_v1.0.xsd" />
...
</schema>
And myserviceB.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.mycompany.com/service/myserviceB/v1.0"
xmlns:em="http://www.mycompany.com/service/errormessage/v1.0"
xmlns:tns="http://www.mycompany.com/service/myserviceB/v1.0"
elementFormDefault="qualified">
<xsd:import namespace="http://www.mycompany.com/service/errormessage/v1.0"
schemaLocation="service_errormessage_v1.0.xsd" />
...
</schema>
Now, my service XSDs are used in service WSDLs:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.mycompany.com/service/myserviceA/v1.0"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="ServiceAWebservice"
targetNamespace="http://www.mycompany.com/service/myserviceA/v1.0">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.mycompany.com/service/myserviceA/v1.0"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" elementFormDefault="qualified">
<xsd:import namespace="http://www.mycompany.com/service/myserviceA/v1.0"
schemaLocation="myserviceA.xsd"/>
</xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.mycompany.com/service/myserviceA/v1.0"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
targetNamespace="http://www.mycompany.com/service/myserviceA/v1.0"/>
</wsdl:types>
...
</wsdl:definitions>
... and a similar ServiceBWebservice.
Now, two packages are generated: myserviceA and myserviceB and both contain the class ErrorcodeType. Of course this isn't really necessary and creates the need for duplicate code in quite a few places, so I'd like to get rid of that. By the way, this is my first contact with SOAP and I'm trying to understand and improve some legacy code from our project, so sorry if this is very obvious, but I haven't found much online.

JAXB XJC bindings: renaming #XmlRootElement and #XmlType together

I have the following XML schema:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="cg" type="cgType"/>
<xsd:complexType name="cgType">
<xsd:sequence>
<xsd:element name="code" type="upperCaseString" minOccurs="1" maxOccurs="1"/>
<xsd:element name="action" type="cgAction" minOccurs="1" maxOccurs="1"/>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="param" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="automated" type="xsd:boolean" default="false" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="cgAction">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="TAKE"/>
<xsd:enumeration value="CLEAR"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="upperCaseString">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[A-Z]*"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
EDIT: I also have the following global bindings:
<?xml version="1.0" encoding="UTF-8" ?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="cg.xsd" node="/xsd:schema">
<jaxb:globalBindings>
<xjc:simple/>
</jaxb:globalBindings>
</jaxb:bindings>
</jaxb:bindings>
Using XJC to generate classes works as expected, with a class named Cg that has both #XmlType and #XmlRootElement annotations. I want to rename that class to be CG, so I changed the binding file to be:
<?xml version="1.0" encoding="UTF-8" ?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="cg.xsd" node="/xsd:schema">
<jaxb:schemaBindings>
<jaxb:package name="foo.bar.cg"/>
</jaxb:schemaBindings>
<jaxb:bindings node="//xsd:element[#name='cg']">
<jaxb:class name="CG"/>
</jaxb:bindings>
<jaxb:bindings node="//xsd:complexType[#name='cgType']">
<jaxb:class name="CG"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
This causes XJC to complain about a collision in the ObjectFactory class between the two CG classes. If I remove the binding on the xsd:element, XJC will now create a CG class as expected, however it misses out the #XmlRootElement annotation. I've experimented with various combinations of bindings on the element and complexType but have been unable to simply rename the default generated class.
How can I rename both the element and the complexType at once?
Both the element and complexType are their own java classes. Using no binding file you should get the result of 2 class files: Cg.java and CgType.java. In your bindings your trying to rename both of those to CG.java which of course is not possible.
What you are probably looking for is to rename the complexType to CGType in which case your bindings should read:
...
<jaxb:bindings node="//xsd:element[#name='cg']">
<jaxb:class name="CG"/>
</jaxb:bindings>
<jaxb:bindings node="//xsd:complexType[#name='cgType']">
<jaxb:class name="CGType"/>
</jaxb:bindings>
...

XSD javaType adapter result in other languages

I've an XSD file containing this:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc"
elementFormDefault="qualified"
targetNamespace="http://example.org/">
<xsd:complexType name="Certificate">
<xsd:sequence>
<xsd:element name="certificate" type="xsd:base64Binary">
<xsd:annotation>
<xsd:appinfo>
<xjc:javaType name="java.security.cert.X509Certificate" adapter="adapters.X509CertificateAdapter" />
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
and when I generate java code with xjc, it produces this:
public class Certificate {
#XmlElement(required = true, type = String.class)
#XmlJavaTypeAdapter(X509CertificateAdapter.class)
#XmlSchemaType(name = "base64Binary")
protected X509Certificate certificate;
....
}
and the adapter works fine.
My question is what will happen when I will give my xsd to a no-java client? What will the Certificate C# class (for example) look like?
You should leave a XSD file as clean as possible by the technology used.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="http://example.org/">
<xsd:complexType name="Certificate">
<xsd:sequence>
<xsd:element name="certificate" type="xsd:base64Binary">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Java-side, to generate the extra information you should use bindings file (XJB).
Following an example of adding an annotation.
<bindings version="2.0" xmlns="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:annox="http://annox.dev.java.net"
xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix">
<bindings schemaLocation="../yourSchema.xsd">
<bindings node="//xs:complexType[#name='User']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement"
name="User">
</annox:annotate>
</annox:annotate>
</bindings>
</bindings>
</bindings>
In this case you need to change this xsd to make it compatible with some other system, becouse you are using specific namespace for java tecnologies.
(i.e. http://java.sun.com/xml/ns/jaxb/xjc)

Can jaxb generate xml pattern like this?

I am expecting a XML generated by JAXB which has the following pattern:
<payload>
<parameters>
<paramName>clientAssocIds</paramName>
<paramVal>0207</paramVal>
<paramName>quoteType</paramName>
<paramVal>NTB</paramVal>
<paramName>quoteDateLimitDays</paramName>
<paramVal>365</paramVal>
<paramName>externalIndicator</paramName>
<paramVal>1</paramVal>
</parameters>
</payload>
The <paramName> and <paramVal> are name and value pairs, which means <paramVal> has to follow <paramName>.
I wrote a XML Schema and use JAXB to generate the java class based on this schema, then I set all the values and marshalled the class, it didn't generate the xml pattern I expected above.
Here is my schema:
<xsd:complexType name="sgrpCommonMessage">
<xsd:sequence>
<xsd:element name="payload" type="payload" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="payload">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="parameters" type="parameter" />
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="parameter">
<xsd:sequence>
<xsd:element minOccurs="0" name="paramName" type="xsd:string" />
<xsd:element minOccurs="0" name="paramVal" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
And the generated xml has a few <parameters>, which is not what I expect. I want to wrap all the <paramName> and <paramVal> pairs in one <parameters>:
<payload>
<parameters>
<paramName>quoteDateLimitDays</paramName>
<paramVal>NTB</paramVal>
</parameters>
<parameters>
<paramName>clientAssocIds</paramName>
<paramVal>0207</paramVal>
</parameters>
<parameters>
<paramName>quoteType</paramName>
<paramVal>NTB</paramVal>
</parameters>
<parameters>
<paramName>externalIndicator</paramName>
<paramVal>NTB</paramVal>
</parameters>
</payload>
I am wondering if JAXB is capable of realizing such XML structure, if not, what API should I use, if yes, how?
You could have an XML schema like the following:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="parameters" type="parameters" />
<xsd:complexType name="parameters">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="paramName" type="xsd:string" />
<xsd:element name="paramValue" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Then with the generated model you could do:
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("forum14571803");
ObjectFactory objectFactory = new ObjectFactory();
Parameters parameters = objectFactory.createParameters();
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamName("A"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamValue("a"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamName("B"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamValue("b"));
JAXBElement<Parameters> root = objectFactory.createParameters(parameters);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Which would give you the following output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<parameters>
<paramName>A</paramName>
<paramValue>a</paramValue>
<paramName>B</paramName>
<paramValue>b</paramValue>
</parameters>

how to fetch content of xml element using idref

I have a XML schema:-
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified">
<xsd:element name="Person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="Book">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Title" type="xsd:string"/>
<xsd:element name="Author">
<xsd:complexType>
<xsd:attribute name="idref" type="xsd:IDREF"
use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Person" />
<xsd:element ref="Book" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
and corresponding to above XML schema, I have following incoming XML:-
<?xml version="1.0" encoding="utf-8" ?>
<root>
<Person id="P234">
<Name>0002</Name>
</Person>
<Book>
<Title>0001</Title>
<Author idref="P234"/>
</Book>
</root>
I know using XML parser validation, I can validate if above XML conforms to my XML schema.for e.g. id and idref should be present. Now what I want to know is which parser(SAX/DOM/STAX) can fetch me complete XML element based on idref. So basically in above example, once parser reaches idref="P234", it should return me complete <Person>...</Person>. Another query is does any parser support id and idref merging, which can replace content of idref with actual element and return me merged XML.
Parsers don't do it, as I know. Use XSLT to do the magic. Moreover, idrefs could be self-referenced, have a cyclic dependency, so it's impossible just "replace content with actual element".
E.g. say you have the xml:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<Person id="P234">
<Name>0002</Name>
<WroteBook idref="B442"/>
</Person>
<Book id="B442">
<Title>0001</Title>
<Author idref="P234"/>
</Book>
</root>
What would you expect from a parser?
An XSLT (not tested myself however):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#idref">
<xsl:apply-templates select="id(.)"/>
</xsl:template>
</xsl:stylesheet>

Categories