@@ -93,6 +93,19 @@ public enum Feature implements FormatFeature
93
93
* @since 2.13
94
94
*/
95
95
UNWRAP_ROOT_OBJECT_NODE (false ),
96
+
97
+ /**
98
+ * Feature that enables automatic conversion of logical property
99
+ * name {@code "xsi:type"} into matching XML name where "type"
100
+ * is the local name and "xsi" prefix is bound to URI
101
+ * {@link XMLConstants#W3C_XML_SCHEMA_INSTANCE_NS_URI},
102
+ * and output is indicated to be done as XML Attribute.
103
+ * This is mostly desirable for Polymorphic handling where it is difficult
104
+ * to specify XML Namespace for type identifier
105
+ *
106
+ * @since 2.17
107
+ */
108
+ AUTO_DETECT_XSI_TYPE (false ),
96
109
;
97
110
98
111
final boolean _defaultState ;
@@ -247,20 +260,26 @@ public void initGenerator() throws IOException
247
260
}
248
261
_initialized = true ;
249
262
try {
263
+ boolean xmlDeclWritten ;
250
264
if (Feature .WRITE_XML_1_1 .enabledIn (_formatFeatures )) {
251
265
_xmlWriter .writeStartDocument ("UTF-8" , "1.1" );
266
+ xmlDeclWritten = true ;
252
267
} else if (Feature .WRITE_XML_DECLARATION .enabledIn (_formatFeatures )) {
253
268
_xmlWriter .writeStartDocument ("UTF-8" , "1.0" );
269
+ xmlDeclWritten = true ;
254
270
} else {
255
- return ;
271
+ xmlDeclWritten = false ;
256
272
}
257
273
// as per [dataformat-xml#172], try adding indentation
258
- if (_xmlPrettyPrinter != null ) {
274
+ if (xmlDeclWritten && ( _xmlPrettyPrinter != null ) ) {
259
275
// ... but only if it is likely to succeed:
260
276
if (!_stax2Emulation ) {
261
277
_xmlPrettyPrinter .writePrologLinefeed (_xmlWriter );
262
278
}
263
279
}
280
+ if (Feature .AUTO_DETECT_XSI_TYPE .enabledIn (_formatFeatures )) {
281
+ _xmlWriter .setPrefix ("xsi" , XMLConstants .W3C_XML_SCHEMA_INSTANCE_NS_URI );
282
+ }
264
283
} catch (XMLStreamException e ) {
265
284
StaxUtil .throwAsGenerationException (e , this );
266
285
}
@@ -487,23 +506,35 @@ public void writeRepeatedFieldName() throws IOException
487
506
/* JsonGenerator method overrides
488
507
/**********************************************************
489
508
*/
490
-
491
- /* Most overrides in this section are just to make methods final,
492
- * to allow better inlining...
493
- */
509
+
510
+ @ Override
511
+ public void writeFieldName (SerializableString name ) throws IOException
512
+ {
513
+ writeFieldName (name .getValue ());
514
+ }
494
515
495
516
@ Override
496
517
public final void writeFieldName (String name ) throws IOException
497
518
{
498
519
if (_writeContext .writeFieldName (name ) == JsonWriteContext .STATUS_EXPECT_VALUE ) {
499
520
_reportError ("Can not write a field name, expecting a value" );
500
521
}
501
- // Should this ever get called?
502
- String ns = (_nextName == null ) ? "" : _nextName .getNamespaceURI ();
503
- _nameToEncode .namespace = ns ;
504
- _nameToEncode .localPart = name ;
505
- _nameProcessor .encodeName (_nameToEncode );
506
- setNextName (new QName (_nameToEncode .namespace , _nameToEncode .localPart ));
522
+
523
+ String ns ;
524
+ // 30-Jan-2024, tatu: Surprise!
525
+ if (Feature .AUTO_DETECT_XSI_TYPE .enabledIn (_formatFeatures )
526
+ && "xsi:type" .equals (name )) {
527
+ setNextName (new QName (XMLConstants .W3C_XML_SCHEMA_INSTANCE_NS_URI ,
528
+ "type" , "xsi" ));
529
+ setNextIsAttribute (true );
530
+ } else {
531
+ // Should this ever get called?
532
+ ns = (_nextName == null ) ? "" : _nextName .getNamespaceURI ();
533
+ _nameToEncode .namespace = ns ;
534
+ _nameToEncode .localPart = name ;
535
+ _nameProcessor .encodeName (_nameToEncode );
536
+ setNextName (new QName (_nameToEncode .namespace , _nameToEncode .localPart ));
537
+ }
507
538
}
508
539
509
540
@ Override
@@ -519,7 +550,7 @@ public final void writeStringField(String fieldName, String value) throws IOExce
519
550
// handling...
520
551
//
521
552
// See [dataformat-xml#4] for more context.
522
-
553
+
523
554
/*
524
555
// @since 2.9
525
556
public WritableTypeId writeTypePrefix(WritableTypeId typeIdDef) throws IOException
@@ -640,12 +671,6 @@ public final void _handleEndObject() throws IOException
640
671
/**********************************************************
641
672
*/
642
673
643
- @ Override
644
- public void writeFieldName (SerializableString name ) throws IOException
645
- {
646
- writeFieldName (name .getValue ());
647
- }
648
-
649
674
@ Override
650
675
public void writeString (String text ) throws IOException
651
676
{
0 commit comments