I have a xml and have to validate against xsd for the structure and data type. but Some fields in the xml has null/empty values. But when using JAXB for validating the xml
"cvc-datatype-valid.1.2.1: '' is not a valid value for 'integer'."
This exception is thrown from JAXB exception with linked SaxParserError Exception. But I have to accept the xml with null values. These threads
validating an XML schema with empty attributes and Element type(long) without content shows we have to modify the xml with respect to xsd such that it should accept the null/empty values.
Is there any other way that I can override the methods of ValidationHandler class and Unmarshaller class to accept null values.
Well I guess you tried to put
<myinteger></myinteger>
in your XML but have an XSD like:
<element name="myinteger" type="integer" />
or
<element minOccurs="0" name="myinteger" type="integer" />
JAXB is right. In terms of XSD validation, this is wrong so you either have to change the XML, change the XSD, or disable validation (will still be wrong but won't crash). MinOccurs="0" means it is accepted that the element is not present at all (remove all the myinteger tags). It doesn't mean that a tag with empty content is accepted. The content must be integer. Empty string is not an integer.
Setting nillable = true doesn't work either. It means that this would be accepted :
<myinteger xsi:nil="true"></myinteger>
But you have to add this xsi:nil="true".
If you do want to accept this:
<myinteger></myinteger>
You can change your XSD as below:
<element name="myinteger" type="IntegerOrNothing" />
<xsd:simpleType name="IntegerOrNoting">
<xsd:union memberTypes="xsd:integer">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="" />
</xsd:restriction>
</xsd:simpleType>
</xsd:union>
</xsd:simpleType>
If you generate your beans from the XSD with Jaxb, fields of this type will be of type String by default. You will then need to use custom bindings to get Integer fields.
Related
When a complexType is marked with mixed="true" in XSD, the generated Java class produces a List with either a "String" type or a JAXBElement wrapper around the actual value. Without mixed="true", the JAXBElement is not produced and the value is directly mapped to the type class. Eg:
<xs:complexType name="div" mixed="true">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="a" minOccurs="0" maxOccurs="unbounded" type="anchorType"/>
</xs:sequence>
...
</complexType>
Here the div type would contain a a List getContent() method that either returns a String or a JAXBElement for AnchorType.
I wanted it to return just either String or AnchorType without the JAXBElement.
Consider this XML which contains a div tag and some child tags:
<parentTag>
<div>myPlainTextValue<a/><a/></div>
</parentTag>
But the mixed content in an XML document does not necessarily occur in a single block.
This XML is also valid according to the XSD:
<parentTag>
<div>my<a/>Plain<a/>Text<a/>Value</div>
</parentTag>
In both cases, the text content of the tag 'div' is 'myPlainTextValue'. But in the second example it is distributed in 4 smaller chunks in between the child tags. JAXB needs to generate code that can handle the general case, so I would not expect it to have a special mode for your case.
I have the following XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:x="MY_NAMESPACE"
targetNamespace="MY_NAMESPACE">
<xs:element name="response" type="x:responseType"/>
<xs:complexType name="responseType">
<xs:all>
<xs:element name="param" type="x:responseParam"/>
</xs:all>
</xs:complexType>
<xs:complexType name="responseParam">
<xs:all>
<xs:element name="value" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:schema>
I use it to generate JAXB classes for unmarshalling a payload like the following:
<x:response xmlns:x="MY_NAMESPACE">
<param>
<value>OK</value>
</param>
</x:response>
via getWebServiceTemplate().marshalSendAndReceive in Spring. Problem is, I also want to unmarshal payloads without the namespace prefix, like this:
<response xmlns="MY_NAMESPACE">
<param>
<value>OK</value>
</param>
</response>
In this case, the response tag is parsed correctly, but the object reference representing param is always null. How can I edit my XSD to make things work? I already tried setting elementFormDefault="qualified" in the schema, or even form="qualified" on the param element.
Additional info that comes to mind (I might edit and add more depending on comments):
The unmarshaller is a Jaxb2Marshaller.
The XML documents
I think you probably know this, but removing that namespace prefix affects the entire document (because the 'param' and 'value' tags do not have any prefix and therefore inherit the default namespace binding). Becauses of this, in the first document the root tag 'response' is in namespace 'MY_NAMESPACE' and the other tags do not have any namespace. In the second document, all of the tags are in namespace 'MY_NAMESPACE'.
The XML Schema
The elementFormDefault attribute defaults to 'unqualified' so your schema should match the first document and reject the second. Your experiments confirm this.
If you set elementFormDefault to 'qualified' then it will reject the first document and match the second one.
There is no value of elementFormDefault that will make the XSD match both XML documents. The namespace is an integral part of the identity of the element.
Possible solution
If you are determined to construct an XSD that matches both documents then it could be done as follows:
explicitly set elementFormDefault to 'unqualified' (optional, but you're about to rely on that setting)b
wrap the current (globally-declared) contents of responseType in a choice group
add a second branch in the choice group containing a local declaration of element 'param' and all of its descendants. Because those are locally declared, they will be in noTargetNamespace.
This is not a general solution to the problem of making JAXB ignore namespaces, and I don't think you will find one (although I'm happy to be corrected by somebody who knows more than I do about JAXB).
Having said all of the above...I think you are probably solving the wrong problem. The JAXB standard is based on XML Schema. An XSD is not meant to tolerate the wrong namespaces. The second XML document is therefore invalid, and should be corrected by whoever is generating it.
I'm working with an XSD schema file (that I cannot change) that defines element XXX as following:
<xsd:element name="XXX" type="Date" minOccurs="0"/>
This produces a java.util.Date in the generated class.
I would need to change how the field is marshalled to XML: if the attribute is null, I would like to produce an empty tag, like if the xsd was:
<xsd:element name="XXX" type="Date" minOccurs="0" nillable=true/>
This produces a JaxbElement in the generated class.
Is it possible to do something like this via Jaxb bindings?
Regards
Giulio
Suggestions:
Pre-process your schema with an XSLT to add nillable where you need it.
Use the jaxb2-simplify-plugin and customize your element with simplify:as-reference-property. I have actually never tried that but maybe it'll work.
Write an XJC plugin.
ps. I'm the author of the mentioned jaxb2-simplify-plugin.
Yes you can.. but isn't a good practice.
<bindings node="//xs:element[#name='XXX']">
<property name="xxx">
<baseType>
<javaType name= "javax.xml.bind.JAXBElement<java.util.Date>"/>
</baseType>
</property>
</bindings>
you should add also below attributes within <javaType> See here Documentation
parseMethod is the name of the parse method to be called during
unmarshalling.
printMethod is the name of the print method to be
called during marshalling.
While working on defining enumeration types in xsd i am facing following problem
I have defined enum structure as :
<xsd:simpleType name="ProvServiceTypeEnumV1">
<xsd:annotation>
<xsd:documentation>
<p>Service Types</p>
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="HOME" />
<xsd:enumeration value="ORIGINAL" />
<xsd:enumeration value="DESTINATION" />
<xsd:enumeration value="WORKING" />
<xsd:enumeration value="PROTECTING" />
<xsd:enumeration value="NA" />
</xsd:restriction>
</xsd:simpleType>
Now i want to use this type ProvServiceTypeEnumV1 as attribute in some other model with default value as "NA" which means when i convert this xsd to java model the default value should always come as NA.
For the boolean types this achieved by using as :
<xsd:element name="cktID" type="xsd:boolean" maxOccurs="1" minOccurs="1"
default="false">
Going by the same methodology i tried using the same for this as :
<xsd:element name="serviceType" type="tns:ProvServiceTypeEnumV1" maxOccurs="1" minOccurs="1"
default="NA">
When i compiled it using xjc i am not getting the default value of serviceType. However boolean value is coming as default
Please suggest what might be missing here.
Thanks
From the JAXB specification (2.0):
The default value is derived from the element declaration’s {value
constraint} property’s value. Unlike attribute defaulting, an element only
defaults when there is an empty element tag in an XML document. The
element’s default value is captured by mapping annotation
#XmlElement.defaultValue(). The unmarshaller sets the
property to this default value when it encounters an empty element tag.
The marshaller can output an empty element tag whenever the element’s
#XmlValue property value is the same as its defaulted value.
This may be disappointing to you, but that's been specified, and I think there's some reason behind this since other variants may appear to be flawed, too.
The main reason for not setting the element by default is that it wouldn't be possible to distinguish a missing element (field == null) from a defaulted value.
Edit
Checking some old examples I have around, I see that the getter generated for an attribute using
<xs:attribute name="field" type="FieldType" use="optional"
default="value1"/>
with FieldType being an enumeration is generated as
public FieldType getField() {
if (field == null) {
return FieldType.VALUE_1;
} else {
return field;
}
}
Note that XML Schema permits a default for an attribute only when use="optional". Obviously, attributes are meant to be another "category" of XML values in contrast to elements.
I have two schemas which are processed using JAXB. The first schema is preprocessed and information of this is used using an episode file (following http://www.java.net/blog/2006/09/05/separate-compilation-jaxb-ri-21).
The second schema imports the first, and again using jaxb, is processed. This all works as expected.
But now I have an element in the first schema, which is used in the second using a reference.
Schema a:
<schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:test="http://www.example.org/Test/"
targetNamespace="http://www.example.org/Test/">
<element name="type" type="test:MyType"></element>
Schema b:
<schema elementFormDefault="qualified"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:second="http://www.example.org/Second/"
xmlns:test="http://www.example.org/Test/"
targetNamespace="http://www.example.org/Second/">
<import namespace="http://www.example.org/Test/" />
<complexType name="SomeType">
<sequence>
<element ref="test:type" minOccurs="1" maxOccurs="unbounded" />
</sequence>
</complexType>
During processing nothing is wrong, but the generated code for both schemas provide the same method:
public JAXBElement<EventType> createType(TypeType value)
At runtime, this results in the following error:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of
IllegalAnnotationExceptions
The element name {http://www.example.org/Type/}type has more than one mapping.
How can I prevent JAXB from creating the duplicate createType methods?
Thanks in advance!
Update: I asked this same question on the JAXB mailing list, on that list I also posted a working example. The thread and example can be found at: http://java.net/projects/jaxb/lists/users/archive/2011-03/message/18
On this list I've been suggested a workaround, and now I can use the schemas the way I like. But I still think JAXB should not create the additional "create" method, since it should already be in the episode file.
I've written a few Schema Definitions in my day. You are declaring your first xsd in your second schema declaration and then you are importing it.
As per MSDN, when you import an XSD you do not include it in the Schema Declaration.
This is where it is in your schema declaration.
xmlns:test="http://www.example.org/Test/"
Remove this and just do the import... ( <xs:import namespace="http://www.example.com/IPO" /> )
see:http://msdn.microsoft.com/en-us/library/ms256480.aspx