Is there a way to specify the Adapter which JAXB uses for marshaling/unmarshaling objects in my XML schema?
For example, if I want to parse the following as an integer:
<SpecialValue>0x1234</SpecialValue>
I can use the following in my schema:
<xs:simpleType name="HexInt">
<xs:annotation>
<xs:appinfo>
<jaxb:javaType name="int" parseMethod="Integer.decode" />
</xs:appinfo>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="0x[0-9a-fA-F]+" />
</xs:restriction>
</xs:simpleType>
<xs:element name="SpecialValue" type="HexInt" />
When I run the schema through the XJC tool, the String "0x1234" should be decoded using Integer.decode() as the Integer with value 0x1234, or 4660 in decimal. The Adapter class that is generated reflects this properly:
public Integer unmarshal(String value) {
return (Integer.decode(value));
}
However, when I want to marshal the value back to an XML element (which is a String literal), the Adapter class does the following:
public String marshal(Integer value) {
if (value == null) {
return null;
}
return value.toString();
}
In this case, the String value of the integer 0x1234 (4660 in decimal) is "4660", which does not adhere to my schema (because it has no "0x" prefix).
How can I tell the Adapter that I want the integer 0x1234 to be marshalled as the "0x1234" String literal? I would be like to be able to do this within the schema so that I can just generate new Java classes without having to modify the output. Is this possible?
Edit: Based on the accepted answer, here is what I did to get this working:
I wrote a method in a class com.example.Parse called toHexString():
public static String toHexString(int value)
{
return ("0x" + Integer.toHexString(value));
}
Then I pointed my schema to that method for printing:
<xs:simpleType name="HexInt">
<xs:annotation>
<xs:appinfo>
<jaxb:javaType name="int" parseMethod="Integer.decode" printMethod="com.example.Parse.toHexString" />
</xs:appinfo>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="0x[0-9a-fA-F]+" />
</xs:restriction>
</xs:simpleType>
Very similar problem: "How to map String coordinates to java.awt.Point ?"
(0) Schema
<xsd:simpleType name="Point">
<xsd:restriction base="xsd:string">
<xsd:pattern value="([0-9])+,([0-9])+" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="HexAreaBorder">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element minOccurs="1" maxOccurs="1" name="type" type="xsd:string" />
<xsd:element minOccurs="1" maxOccurs="1" name="name" type="xsd:string" />
<xsd:element name="points" type="Point" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
(1) Create adapter class that extends XmlAdapter.
package com.kjcode.hexgrid.jaxbadapter;
import java.awt.Point;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class PointAdapter extends XmlAdapter<String, Point> {
@Override
public Point unmarshal(String v) throws Exception {
String[] coords = v.split(",");
return new Point(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]));
}
@Override
public String marshal(Point v) throws Exception {
return String.format("%d,%d", v.x, v.y);
}
}
(2) Create bindings file. The key is to add: jaxb:extensionBindingPrefixes="xjc" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:extensionBindingPrefixes="xjc" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns="hexmap" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="hexmap.xsd">
<jaxb:globalBindings>
<xjc:javaType adapter="com.kjcode.hexgrid.jaxbadapter.PointAdapter" name="java.awt.Point" xmlType="Point" />
</jaxb:globalBindings>
</jaxb:bindings>
</jaxb:bindings>
(3) Configure pom.xml
<plugin>
<groupId>com.sun.tools.xjc.maven2</groupId>
<artifactId>maven-jaxb-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generatePackage>com.kjcode.hexmap.api.logic.field.generated</generatePackage>
<extension>true</extension>
</configuration>
</plugin>
(4) JAXB will generate
public class HexAreaBorder {
@XmlElement(required = true)
protected String type;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(PointAdapter.class)
protected List<Point> points = new LinkedList<Point>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With