Jakarta XML Binding API that automates the mapping between XML documents and Java objects through data binding
—
Jakarta XML Binding provides comprehensive static utility methods for converting between Java types and XML Schema data types. The DatatypeConverter class handles all standard XML Schema primitive and derived types with robust parsing and formatting capabilities.
The DatatypeConverter class provides static methods for all XML Schema data types, supporting both parsing (String to Java) and printing (Java to String) operations.
public final class DatatypeConverter {
// String type conversion
public static String parseString(String lexicalXSDString);
public static String printString(String val);
// Integer type conversions
public static java.math.BigInteger parseInteger(String lexicalXSDInteger);
public static String printInteger(java.math.BigInteger val);
public static int parseInt(String lexicalXSDInt);
public static String printInt(int val);
public static long parseLong(String lexicalXSDLong);
public static String printLong(long val);
public static short parseShort(String lexicalXSDShort);
public static String printShort(short val);
public static byte parseByte(String lexicalXSDByte);
public static String printByte(byte val);
// Unsigned integer conversions
public static long parseUnsignedInt(String lexicalXSDUnsignedInt);
public static String printUnsignedInt(long val);
public static int parseUnsignedShort(String lexicalXSDUnsignedShort);
public static String printUnsignedShort(int val);
// Decimal type conversions
public static java.math.BigDecimal parseDecimal(String lexicalXSDDecimal);
public static String printDecimal(java.math.BigDecimal val);
public static float parseFloat(String lexicalXSDFloat);
public static String printFloat(float val);
public static double parseDouble(String lexicalXSDDouble);
public static String printDouble(double val);
// Boolean conversion
public static boolean parseBoolean(String lexicalXSDBoolean);
public static String printBoolean(boolean val);
// Date and time conversions
public static java.util.Calendar parseDateTime(String lexicalXSDDateTime);
public static String printDateTime(java.util.Calendar val);
public static java.util.Calendar parseTime(String lexicalXSDTime);
public static String printTime(java.util.Calendar val);
public static java.util.Calendar parseDate(String lexicalXSDDate);
public static String printDate(java.util.Calendar val);
// Binary data conversions
public static byte[] parseBase64Binary(String lexicalXSDBase64Binary);
public static String printBase64Binary(byte[] val);
public static byte[] parseHexBinary(String lexicalXSDHexBinary);
public static String printHexBinary(byte[] val);
// QName conversion
public static javax.xml.namespace.QName parseQName(String lexicalXSDQName, javax.xml.namespace.NamespaceContext nsc);
public static String printQName(javax.xml.namespace.QName val, javax.xml.namespace.NamespaceContext nsc);
// Generic any simple type
public static String parseAnySimpleType(String lexicalXSDAnySimpleType);
public static String printAnySimpleType(String val);
// Converter management
public static void setDatatypeConverter(DatatypeConverterInterface converter);
}Simple conversions for XML Schema primitive types.
Usage Examples:
// String conversions (identity operations with validation)
String xmlString = DatatypeConverter.printString("Hello World");
String javaString = DatatypeConverter.parseString(xmlString);
// Integer conversions
String xmlInt = DatatypeConverter.printInt(42);
int javaInt = DatatypeConverter.parseInt("42");
String xmlLong = DatatypeConverter.printLong(123456789L);
long javaLong = DatatypeConverter.parseLong("123456789");
BigInteger bigInt = DatatypeConverter.parseInteger("99999999999999999999");
String xmlBigInt = DatatypeConverter.printInteger(bigInt);
// Decimal conversions
BigDecimal decimal = DatatypeConverter.parseDecimal("123.456");
String xmlDecimal = DatatypeConverter.printDecimal(new BigDecimal("123.456"));
double d = DatatypeConverter.parseDouble("3.14159");
String xmlDouble = DatatypeConverter.printDouble(3.14159);
// Boolean conversion
boolean bool = DatatypeConverter.parseBoolean("true"); // or "1"
String xmlBool = DatatypeConverter.printBoolean(true); // "true"
// Handles XML Schema boolean values: true, false, 1, 0
boolean xmlTrue = DatatypeConverter.parseBoolean("1"); // true
boolean xmlFalse = DatatypeConverter.parseBoolean("0"); // falseXML Schema date/time types map to Java Calendar objects with proper timezone handling.
Usage Examples:
// DateTime conversion (ISO 8601 format)
String xmlDateTime = "2023-12-25T10:30:00Z";
Calendar dateTime = DatatypeConverter.parseDateTime(xmlDateTime);
Calendar now = Calendar.getInstance();
String xmlNow = DatatypeConverter.printDateTime(now);
// Output: "2023-12-25T10:30:00.000Z" (with timezone)
// Date conversion (date only)
String xmlDate = "2023-12-25";
Calendar date = DatatypeConverter.parseDate(xmlDate);
Calendar today = Calendar.getInstance();
String xmlToday = DatatypeConverter.printDate(today);
// Output: "2023-12-25Z" (with timezone info)
// Time conversion (time only)
String xmlTime = "14:30:00";
Calendar time = DatatypeConverter.parseTime(xmlTime);
Calendar currentTime = Calendar.getInstance();
String xmlCurrentTime = DatatypeConverter.printTime(currentTime);
// Output: "14:30:00.000Z" (with timezone)
// Working with timezones
String dateTimeWithTZ = "2023-12-25T10:30:00-05:00";
Calendar parsedWithTZ = DatatypeConverter.parseDateTime(dateTimeWithTZ);
// Get timezone information
TimeZone tz = parsedWithTZ.getTimeZone();
int offset = tz.getOffset(parsedWithTZ.getTimeInMillis());XML Schema supports two binary data encoding formats: Base64 and hexadecimal.
Usage Examples:
// Base64 binary conversion
byte[] binaryData = "Hello World".getBytes("UTF-8");
String base64 = DatatypeConverter.printBase64Binary(binaryData);
// Output: "SGVsbG8gV29ybGQ="
byte[] decodedBase64 = DatatypeConverter.parseBase64Binary(base64);
String originalText = new String(decodedBase64, "UTF-8");
// Hexadecimal binary conversion
String hex = DatatypeConverter.printHexBinary(binaryData);
// Output: "48656C6C6F20576F726C64"
byte[] decodedHex = DatatypeConverter.parseHexBinary(hex);
// Working with larger binary data
try (FileInputStream fis = new FileInputStream("document.pdf")) {
byte[] fileBytes = fis.readAllBytes();
String base64Document = DatatypeConverter.printBase64Binary(fileBytes);
// Store base64Document in XML
// Later retrieve and decode:
byte[] restoredBytes = DatatypeConverter.parseBase64Binary(base64Document);
try (FileOutputStream fos = new FileOutputStream("restored.pdf")) {
fos.write(restoredBytes);
}
}QName conversions require namespace context for proper prefix resolution.
Usage Examples:
// Create namespace context
NamespaceContext nsContext = new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "hr": return "http://company.com/hr";
case "common": return "http://company.com/common";
case XMLConstants.XML_NS_PREFIX: return XMLConstants.XML_NS_URI;
case XMLConstants.XMLNS_ATTRIBUTE: return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
default: return XMLConstants.NULL_NS_URI;
}
}
@Override
public String getPrefix(String namespaceURI) {
switch (namespaceURI) {
case "http://company.com/hr": return "hr";
case "http://company.com/common": return "common";
default: return null;
}
}
@Override
public Iterator<String> getPrefixes(String namespaceURI) {
return Collections.singletonList(getPrefix(namespaceURI)).iterator();
}
};
// Parse QName from XML
String xmlQName = "hr:employee";
QName qname = DatatypeConverter.parseQName(xmlQName, nsContext);
// QName{http://company.com/hr}employee
// Print QName to XML
QName qnameToSerialize = new QName("http://company.com/hr", "employee");
String xmlOutput = DatatypeConverter.printQName(qnameToSerialize, nsContext);
// Output: "hr:employee"
// Handle unprefixed QNames (default namespace)
QName localName = new QName("employee"); // No namespace
String xmlLocal = DatatypeConverter.printQName(localName, nsContext);
// Output: "employee"The interface that defines the contract for all datatype conversion operations.
public interface DatatypeConverterInterface {
// String type conversion
String parseString(String lexicalXSDString);
String printString(String val);
// Integer type conversions
java.math.BigInteger parseInteger(String lexicalXSDInteger);
String printInteger(java.math.BigInteger val);
int parseInt(String lexicalXSDInt);
String printInt(int val);
long parseLong(String lexicalXSDLong);
String printLong(long val);
short parseShort(String lexicalXSDShort);
String printShort(short val);
byte parseByte(String lexicalXSDByte);
String printByte(byte val);
// Unsigned integer conversions
long parseUnsignedInt(String lexicalXSDUnsignedInt);
String printUnsignedInt(long val);
int parseUnsignedShort(String lexicalXSDUnsignedShort);
String printUnsignedShort(int val);
// Decimal type conversions
java.math.BigDecimal parseDecimal(String lexicalXSDDecimal);
String printDecimal(java.math.BigDecimal val);
float parseFloat(String lexicalXSDFloat);
String printFloat(float val);
double parseDouble(String lexicalXSDDouble);
String printDouble(double val);
// Boolean conversion
boolean parseBoolean(String lexicalXSDBoolean);
String printBoolean(boolean val);
// Date and time conversions
java.util.Calendar parseDateTime(String lexicalXSDDateTime);
String printDateTime(java.util.Calendar val);
java.util.Calendar parseTime(String lexicalXSDTime);
String printTime(java.util.Calendar val);
java.util.Calendar parseDate(String lexicalXSDDate);
String printDate(java.util.Calendar val);
// Binary data conversions
byte[] parseBase64Binary(String lexicalXSDBase64Binary);
String printBase64Binary(byte[] val);
byte[] parseHexBinary(String lexicalXSDHexBinary);
String printHexBinary(byte[] val);
// QName conversion
javax.xml.namespace.QName parseQName(String lexicalXSDQName, javax.xml.namespace.NamespaceContext nsc);
String printQName(javax.xml.namespace.QName val, javax.xml.namespace.NamespaceContext nsc);
// Generic any simple type
String parseAnySimpleType(String lexicalXSDAnySimpleType);
String printAnySimpleType(String val);
}You can provide custom implementations of the DatatypeConverterInterface for specialized processing.
Usage Example:
// Custom converter with enhanced date handling
public class CustomDatatypeConverter implements DatatypeConverterInterface {
private static final DateTimeFormatter CUSTOM_DATE_FORMAT =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public Calendar parseDateTime(String lexicalXSDDateTime) {
try {
// Try standard XML Schema format first
return javax.xml.bind.DatatypeConverter.parseDateTime(lexicalXSDDateTime);
} catch (Exception e) {
// Fall back to custom format
LocalDateTime ldt = LocalDateTime.parse(lexicalXSDDateTime, CUSTOM_DATE_FORMAT);
Calendar cal = Calendar.getInstance();
cal.setTime(Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()));
return cal;
}
}
@Override
public String printDateTime(Calendar val) {
// Use standard XML Schema format for output
return javax.xml.bind.DatatypeConverter.printDateTime(val);
}
// Implement other methods by delegating to default implementation
@Override
public String parseString(String lexicalXSDString) {
return javax.xml.bind.DatatypeConverter.parseString(lexicalXSDString);
}
// ... implement remaining methods
}
// Set custom converter
DatatypeConverter.setDatatypeConverter(new CustomDatatypeConverter());
// Now all JAXB operations will use the custom converter// Handle parsing errors gracefully
public class SafeDataTypeUtils {
public static Integer parseIntSafely(String value) {
try {
return DatatypeConverter.parseInt(value);
} catch (NumberFormatException e) {
System.err.println("Invalid integer format: " + value);
return null;
}
}
public static Calendar parseDateTimeSafely(String value) {
try {
return DatatypeConverter.parseDateTime(value);
} catch (IllegalArgumentException e) {
System.err.println("Invalid datetime format: " + value);
return null;
}
}
public static byte[] parseBase64Safely(String value) {
try {
return DatatypeConverter.parseBase64Binary(value);
} catch (IllegalArgumentException e) {
System.err.println("Invalid base64 format: " + value);
return null;
}
}
}// Safe handling of null and empty values
public class NullSafeConverter {
public static String printStringSafe(String value) {
return value != null ? DatatypeConverter.printString(value) : null;
}
public static String parseStringSafe(String xmlValue) {
return xmlValue != null && !xmlValue.isEmpty()
? DatatypeConverter.parseString(xmlValue)
: null;
}
public static String printCalendarSafe(Calendar value) {
return value != null ? DatatypeConverter.printDateTime(value) : null;
}
public static String printBinarySafe(byte[] value) {
return value != null && value.length > 0
? DatatypeConverter.printBase64Binary(value)
: null;
}
}// Validation utilities for XML Schema types
public class XSDTypeValidator {
private static final Pattern XSD_DATETIME_PATTERN = Pattern.compile(
"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})?"
);
private static final Pattern XSD_DATE_PATTERN = Pattern.compile(
"\\d{4}-\\d{2}-\\d{2}(Z|[+-]\\d{2}:\\d{2})?"
);
public static boolean isValidDateTime(String value) {
if (value == null || value.isEmpty()) return false;
try {
DatatypeConverter.parseDateTime(value);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isValidBase64(String value) {
if (value == null || value.isEmpty()) return false;
try {
DatatypeConverter.parseBase64Binary(value);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isValidInteger(String value) {
if (value == null || value.isEmpty()) return false;
try {
DatatypeConverter.parseInteger(value);
return true;
} catch (Exception e) {
return false;
}
}
}The DatatypeConverter is automatically used by JAXB during marshalling and unmarshalling operations:
// JAXB automatically uses DatatypeConverter for built-in types
@XmlRootElement
public class Document {
@XmlElement
private Calendar createdDate; // Uses parseDateTime/printDateTime
@XmlElement
private BigDecimal amount; // Uses parseDecimal/printDecimal
@XmlElement
private byte[] signature; // Uses parseBase64Binary/printBase64Binary
@XmlAttribute
private boolean active; // Uses parseBoolean/printBoolean
}
// Custom converter affects all JAXB operations
DatatypeConverter.setDatatypeConverter(new CustomDatatypeConverter());
JAXBContext context = JAXBContext.newInstance(Document.class);
// All marshalling/unmarshalling now uses custom converterInstall with Tessl CLI
npx tessl i tessl/maven-jakarta-xml-bind--jakarta-xml-bind-api