0
# Data Type Conversion
1
2
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.
3
4
## Capabilities
5
6
### DatatypeConverter Static Methods
7
8
The DatatypeConverter class provides static methods for all XML Schema data types, supporting both parsing (String to Java) and printing (Java to String) operations.
9
10
```java { .api }
11
public final class DatatypeConverter {
12
// String type conversion
13
public static String parseString(String lexicalXSDString);
14
public static String printString(String val);
15
16
// Integer type conversions
17
public static java.math.BigInteger parseInteger(String lexicalXSDInteger);
18
public static String printInteger(java.math.BigInteger val);
19
20
public static int parseInt(String lexicalXSDInt);
21
public static String printInt(int val);
22
23
public static long parseLong(String lexicalXSDLong);
24
public static String printLong(long val);
25
26
public static short parseShort(String lexicalXSDShort);
27
public static String printShort(short val);
28
29
public static byte parseByte(String lexicalXSDByte);
30
public static String printByte(byte val);
31
32
// Unsigned integer conversions
33
public static long parseUnsignedInt(String lexicalXSDUnsignedInt);
34
public static String printUnsignedInt(long val);
35
36
public static int parseUnsignedShort(String lexicalXSDUnsignedShort);
37
public static String printUnsignedShort(int val);
38
39
// Decimal type conversions
40
public static java.math.BigDecimal parseDecimal(String lexicalXSDDecimal);
41
public static String printDecimal(java.math.BigDecimal val);
42
43
public static float parseFloat(String lexicalXSDFloat);
44
public static String printFloat(float val);
45
46
public static double parseDouble(String lexicalXSDDouble);
47
public static String printDouble(double val);
48
49
// Boolean conversion
50
public static boolean parseBoolean(String lexicalXSDBoolean);
51
public static String printBoolean(boolean val);
52
53
// Date and time conversions
54
public static java.util.Calendar parseDateTime(String lexicalXSDDateTime);
55
public static String printDateTime(java.util.Calendar val);
56
57
public static java.util.Calendar parseTime(String lexicalXSDTime);
58
public static String printTime(java.util.Calendar val);
59
60
public static java.util.Calendar parseDate(String lexicalXSDDate);
61
public static String printDate(java.util.Calendar val);
62
63
// Binary data conversions
64
public static byte[] parseBase64Binary(String lexicalXSDBase64Binary);
65
public static String printBase64Binary(byte[] val);
66
67
public static byte[] parseHexBinary(String lexicalXSDHexBinary);
68
public static String printHexBinary(byte[] val);
69
70
// QName conversion
71
public static javax.xml.namespace.QName parseQName(String lexicalXSDQName, javax.xml.namespace.NamespaceContext nsc);
72
public static String printQName(javax.xml.namespace.QName val, javax.xml.namespace.NamespaceContext nsc);
73
74
// Generic any simple type
75
public static String parseAnySimpleType(String lexicalXSDAnySimpleType);
76
public static String printAnySimpleType(String val);
77
78
// Converter management
79
public static void setDatatypeConverter(DatatypeConverterInterface converter);
80
}
81
```
82
83
### Basic Type Conversions
84
85
Simple conversions for XML Schema primitive types.
86
87
**Usage Examples:**
88
89
```java
90
// String conversions (identity operations with validation)
91
String xmlString = DatatypeConverter.printString("Hello World");
92
String javaString = DatatypeConverter.parseString(xmlString);
93
94
// Integer conversions
95
String xmlInt = DatatypeConverter.printInt(42);
96
int javaInt = DatatypeConverter.parseInt("42");
97
98
String xmlLong = DatatypeConverter.printLong(123456789L);
99
long javaLong = DatatypeConverter.parseLong("123456789");
100
101
BigInteger bigInt = DatatypeConverter.parseInteger("99999999999999999999");
102
String xmlBigInt = DatatypeConverter.printInteger(bigInt);
103
104
// Decimal conversions
105
BigDecimal decimal = DatatypeConverter.parseDecimal("123.456");
106
String xmlDecimal = DatatypeConverter.printDecimal(new BigDecimal("123.456"));
107
108
double d = DatatypeConverter.parseDouble("3.14159");
109
String xmlDouble = DatatypeConverter.printDouble(3.14159);
110
111
// Boolean conversion
112
boolean bool = DatatypeConverter.parseBoolean("true"); // or "1"
113
String xmlBool = DatatypeConverter.printBoolean(true); // "true"
114
115
// Handles XML Schema boolean values: true, false, 1, 0
116
boolean xmlTrue = DatatypeConverter.parseBoolean("1"); // true
117
boolean xmlFalse = DatatypeConverter.parseBoolean("0"); // false
118
```
119
120
### Date and Time Conversions
121
122
XML Schema date/time types map to Java Calendar objects with proper timezone handling.
123
124
**Usage Examples:**
125
126
```java
127
// DateTime conversion (ISO 8601 format)
128
String xmlDateTime = "2023-12-25T10:30:00Z";
129
Calendar dateTime = DatatypeConverter.parseDateTime(xmlDateTime);
130
131
Calendar now = Calendar.getInstance();
132
String xmlNow = DatatypeConverter.printDateTime(now);
133
// Output: "2023-12-25T10:30:00.000Z" (with timezone)
134
135
// Date conversion (date only)
136
String xmlDate = "2023-12-25";
137
Calendar date = DatatypeConverter.parseDate(xmlDate);
138
139
Calendar today = Calendar.getInstance();
140
String xmlToday = DatatypeConverter.printDate(today);
141
// Output: "2023-12-25Z" (with timezone info)
142
143
// Time conversion (time only)
144
String xmlTime = "14:30:00";
145
Calendar time = DatatypeConverter.parseTime(xmlTime);
146
147
Calendar currentTime = Calendar.getInstance();
148
String xmlCurrentTime = DatatypeConverter.printTime(currentTime);
149
// Output: "14:30:00.000Z" (with timezone)
150
151
// Working with timezones
152
String dateTimeWithTZ = "2023-12-25T10:30:00-05:00";
153
Calendar parsedWithTZ = DatatypeConverter.parseDateTime(dateTimeWithTZ);
154
155
// Get timezone information
156
TimeZone tz = parsedWithTZ.getTimeZone();
157
int offset = tz.getOffset(parsedWithTZ.getTimeInMillis());
158
```
159
160
### Binary Data Conversions
161
162
XML Schema supports two binary data encoding formats: Base64 and hexadecimal.
163
164
**Usage Examples:**
165
166
```java
167
// Base64 binary conversion
168
byte[] binaryData = "Hello World".getBytes("UTF-8");
169
String base64 = DatatypeConverter.printBase64Binary(binaryData);
170
// Output: "SGVsbG8gV29ybGQ="
171
172
byte[] decodedBase64 = DatatypeConverter.parseBase64Binary(base64);
173
String originalText = new String(decodedBase64, "UTF-8");
174
175
// Hexadecimal binary conversion
176
String hex = DatatypeConverter.printHexBinary(binaryData);
177
// Output: "48656C6C6F20576F726C64"
178
179
byte[] decodedHex = DatatypeConverter.parseHexBinary(hex);
180
181
// Working with larger binary data
182
try (FileInputStream fis = new FileInputStream("document.pdf")) {
183
byte[] fileBytes = fis.readAllBytes();
184
String base64Document = DatatypeConverter.printBase64Binary(fileBytes);
185
186
// Store base64Document in XML
187
// Later retrieve and decode:
188
byte[] restoredBytes = DatatypeConverter.parseBase64Binary(base64Document);
189
190
try (FileOutputStream fos = new FileOutputStream("restored.pdf")) {
191
fos.write(restoredBytes);
192
}
193
}
194
```
195
196
### QName Conversions
197
198
QName conversions require namespace context for proper prefix resolution.
199
200
**Usage Examples:**
201
202
```java
203
// Create namespace context
204
NamespaceContext nsContext = new NamespaceContext() {
205
@Override
206
public String getNamespaceURI(String prefix) {
207
switch (prefix) {
208
case "hr": return "http://company.com/hr";
209
case "common": return "http://company.com/common";
210
case XMLConstants.XML_NS_PREFIX: return XMLConstants.XML_NS_URI;
211
case XMLConstants.XMLNS_ATTRIBUTE: return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
212
default: return XMLConstants.NULL_NS_URI;
213
}
214
}
215
216
@Override
217
public String getPrefix(String namespaceURI) {
218
switch (namespaceURI) {
219
case "http://company.com/hr": return "hr";
220
case "http://company.com/common": return "common";
221
default: return null;
222
}
223
}
224
225
@Override
226
public Iterator<String> getPrefixes(String namespaceURI) {
227
return Collections.singletonList(getPrefix(namespaceURI)).iterator();
228
}
229
};
230
231
// Parse QName from XML
232
String xmlQName = "hr:employee";
233
QName qname = DatatypeConverter.parseQName(xmlQName, nsContext);
234
// QName{http://company.com/hr}employee
235
236
// Print QName to XML
237
QName qnameToSerialize = new QName("http://company.com/hr", "employee");
238
String xmlOutput = DatatypeConverter.printQName(qnameToSerialize, nsContext);
239
// Output: "hr:employee"
240
241
// Handle unprefixed QNames (default namespace)
242
QName localName = new QName("employee"); // No namespace
243
String xmlLocal = DatatypeConverter.printQName(localName, nsContext);
244
// Output: "employee"
245
```
246
247
### DatatypeConverterInterface
248
249
The interface that defines the contract for all datatype conversion operations.
250
251
```java { .api }
252
public interface DatatypeConverterInterface {
253
// String type conversion
254
String parseString(String lexicalXSDString);
255
String printString(String val);
256
257
// Integer type conversions
258
java.math.BigInteger parseInteger(String lexicalXSDInteger);
259
String printInteger(java.math.BigInteger val);
260
261
int parseInt(String lexicalXSDInt);
262
String printInt(int val);
263
264
long parseLong(String lexicalXSDLong);
265
String printLong(long val);
266
267
short parseShort(String lexicalXSDShort);
268
String printShort(short val);
269
270
byte parseByte(String lexicalXSDByte);
271
String printByte(byte val);
272
273
// Unsigned integer conversions
274
long parseUnsignedInt(String lexicalXSDUnsignedInt);
275
String printUnsignedInt(long val);
276
277
int parseUnsignedShort(String lexicalXSDUnsignedShort);
278
String printUnsignedShort(int val);
279
280
// Decimal type conversions
281
java.math.BigDecimal parseDecimal(String lexicalXSDDecimal);
282
String printDecimal(java.math.BigDecimal val);
283
284
float parseFloat(String lexicalXSDFloat);
285
String printFloat(float val);
286
287
double parseDouble(String lexicalXSDDouble);
288
String printDouble(double val);
289
290
// Boolean conversion
291
boolean parseBoolean(String lexicalXSDBoolean);
292
String printBoolean(boolean val);
293
294
// Date and time conversions
295
java.util.Calendar parseDateTime(String lexicalXSDDateTime);
296
String printDateTime(java.util.Calendar val);
297
298
java.util.Calendar parseTime(String lexicalXSDTime);
299
String printTime(java.util.Calendar val);
300
301
java.util.Calendar parseDate(String lexicalXSDDate);
302
String printDate(java.util.Calendar val);
303
304
// Binary data conversions
305
byte[] parseBase64Binary(String lexicalXSDBase64Binary);
306
String printBase64Binary(byte[] val);
307
308
byte[] parseHexBinary(String lexicalXSDHexBinary);
309
String printHexBinary(byte[] val);
310
311
// QName conversion
312
javax.xml.namespace.QName parseQName(String lexicalXSDQName, javax.xml.namespace.NamespaceContext nsc);
313
String printQName(javax.xml.namespace.QName val, javax.xml.namespace.NamespaceContext nsc);
314
315
// Generic any simple type
316
String parseAnySimpleType(String lexicalXSDAnySimpleType);
317
String printAnySimpleType(String val);
318
}
319
```
320
321
### Custom Converter Implementation
322
323
You can provide custom implementations of the DatatypeConverterInterface for specialized processing.
324
325
**Usage Example:**
326
327
```java
328
// Custom converter with enhanced date handling
329
public class CustomDatatypeConverter implements DatatypeConverterInterface {
330
private static final DateTimeFormatter CUSTOM_DATE_FORMAT =
331
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
332
333
@Override
334
public Calendar parseDateTime(String lexicalXSDDateTime) {
335
try {
336
// Try standard XML Schema format first
337
return javax.xml.bind.DatatypeConverter.parseDateTime(lexicalXSDDateTime);
338
} catch (Exception e) {
339
// Fall back to custom format
340
LocalDateTime ldt = LocalDateTime.parse(lexicalXSDDateTime, CUSTOM_DATE_FORMAT);
341
Calendar cal = Calendar.getInstance();
342
cal.setTime(Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()));
343
return cal;
344
}
345
}
346
347
@Override
348
public String printDateTime(Calendar val) {
349
// Use standard XML Schema format for output
350
return javax.xml.bind.DatatypeConverter.printDateTime(val);
351
}
352
353
// Implement other methods by delegating to default implementation
354
@Override
355
public String parseString(String lexicalXSDString) {
356
return javax.xml.bind.DatatypeConverter.parseString(lexicalXSDString);
357
}
358
359
// ... implement remaining methods
360
}
361
362
// Set custom converter
363
DatatypeConverter.setDatatypeConverter(new CustomDatatypeConverter());
364
365
// Now all JAXB operations will use the custom converter
366
```
367
368
## Error Handling and Edge Cases
369
370
### Common Parsing Errors
371
372
```java
373
// Handle parsing errors gracefully
374
public class SafeDataTypeUtils {
375
376
public static Integer parseIntSafely(String value) {
377
try {
378
return DatatypeConverter.parseInt(value);
379
} catch (NumberFormatException e) {
380
System.err.println("Invalid integer format: " + value);
381
return null;
382
}
383
}
384
385
public static Calendar parseDateTimeSafely(String value) {
386
try {
387
return DatatypeConverter.parseDateTime(value);
388
} catch (IllegalArgumentException e) {
389
System.err.println("Invalid datetime format: " + value);
390
return null;
391
}
392
}
393
394
public static byte[] parseBase64Safely(String value) {
395
try {
396
return DatatypeConverter.parseBase64Binary(value);
397
} catch (IllegalArgumentException e) {
398
System.err.println("Invalid base64 format: " + value);
399
return null;
400
}
401
}
402
}
403
```
404
405
### Null and Empty Value Handling
406
407
```java
408
// Safe handling of null and empty values
409
public class NullSafeConverter {
410
411
public static String printStringSafe(String value) {
412
return value != null ? DatatypeConverter.printString(value) : null;
413
}
414
415
public static String parseStringSafe(String xmlValue) {
416
return xmlValue != null && !xmlValue.isEmpty()
417
? DatatypeConverter.parseString(xmlValue)
418
: null;
419
}
420
421
public static String printCalendarSafe(Calendar value) {
422
return value != null ? DatatypeConverter.printDateTime(value) : null;
423
}
424
425
public static String printBinarySafe(byte[] value) {
426
return value != null && value.length > 0
427
? DatatypeConverter.printBase64Binary(value)
428
: null;
429
}
430
}
431
```
432
433
### Validation and Format Checking
434
435
```java
436
// Validation utilities for XML Schema types
437
public class XSDTypeValidator {
438
439
private static final Pattern XSD_DATETIME_PATTERN = Pattern.compile(
440
"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})?"
441
);
442
443
private static final Pattern XSD_DATE_PATTERN = Pattern.compile(
444
"\\d{4}-\\d{2}-\\d{2}(Z|[+-]\\d{2}:\\d{2})?"
445
);
446
447
public static boolean isValidDateTime(String value) {
448
if (value == null || value.isEmpty()) return false;
449
450
try {
451
DatatypeConverter.parseDateTime(value);
452
return true;
453
} catch (Exception e) {
454
return false;
455
}
456
}
457
458
public static boolean isValidBase64(String value) {
459
if (value == null || value.isEmpty()) return false;
460
461
try {
462
DatatypeConverter.parseBase64Binary(value);
463
return true;
464
} catch (Exception e) {
465
return false;
466
}
467
}
468
469
public static boolean isValidInteger(String value) {
470
if (value == null || value.isEmpty()) return false;
471
472
try {
473
DatatypeConverter.parseInteger(value);
474
return true;
475
} catch (Exception e) {
476
return false;
477
}
478
}
479
}
480
```
481
482
## Integration with JAXB Processing
483
484
The DatatypeConverter is automatically used by JAXB during marshalling and unmarshalling operations:
485
486
```java
487
// JAXB automatically uses DatatypeConverter for built-in types
488
@XmlRootElement
489
public class Document {
490
@XmlElement
491
private Calendar createdDate; // Uses parseDateTime/printDateTime
492
493
@XmlElement
494
private BigDecimal amount; // Uses parseDecimal/printDecimal
495
496
@XmlElement
497
private byte[] signature; // Uses parseBase64Binary/printBase64Binary
498
499
@XmlAttribute
500
private boolean active; // Uses parseBoolean/printBoolean
501
}
502
503
// Custom converter affects all JAXB operations
504
DatatypeConverter.setDatatypeConverter(new CustomDatatypeConverter());
505
506
JAXBContext context = JAXBContext.newInstance(Document.class);
507
// All marshalling/unmarshalling now uses custom converter
508
```