Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Project: jackson-dataformat-xml

#508: `XmlMapper` is unable to deserialise into an empty record
(reported by @protazy)
#714: Root-level `null` handling (via `xsi:nil`) leaves trailing token in
`JsonParser`-exposed token stream
#745: Add feature to include `standalone='yes'` in xml declaration
(contributed by @duoduobingbing)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ private Feature(boolean defaultState) {
*/

/**
* Bitfield that indicates which numeric representations
* Bit field that indicates which numeric representations
* have been calculated for the current type
*/
protected int _numTypesValid = NR_UNKNOWN;
Expand Down Expand Up @@ -297,6 +297,8 @@ public FromXmlParser(IOContext ctxt, int genericParserFeatures, int xmlFeatures,
// changed in 2.10.2
if (_xmlTokens.hasXsiNil()) {
_nextToken = JsonToken.VALUE_NULL;
// 21-Apr-2025, tatu: [dataformat-xml#714] Must "flush" the stream
_xmlTokens.markAsStreamEnd();
} else {
switch (firstToken) {
case XmlTokenStream.XML_START_ELEMENT:
Expand Down Expand Up @@ -689,16 +691,16 @@ public JsonToken nextToken() throws IOException
{
JsonToken t = nextToken0();
if (t != null) {
final String loc = (_parsingContext == null) ? "NULL" : String.valueOf(_parsingContext.pathAsPointer());
final String loc = (_parsingContext == null) ? "<null>" : "'"+String.valueOf(_parsingContext.pathAsPointer())+"'";
switch (t) {
case FIELD_NAME:
System.out.printf("FromXmlParser.nextToken() at '%s': JsonToken.FIELD_NAME '%s'\n", loc, _parsingContext.currentName());
System.out.printf("FromXmlParser.nextToken() at %s: JsonToken.FIELD_NAME '%s'\n", loc, _parsingContext.getCurrentName());
break;
case VALUE_STRING:
System.out.printf("FromXmlParser.nextToken() at '%s': JsonToken.VALUE_STRING '%s'\n", loc, getText());
System.out.printf("FromXmlParser.nextToken() at %s: JsonToken.VALUE_STRING '%s'\n", loc, getText());
break;
default:
System.out.printf("FromXmlParser.nextToken() at '%s': %s\n", loc, t);
System.out.printf("FromXmlParser.nextToken() at %s: %s\n", loc, t);
}
}
return t;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,6 @@ public int next() throws XMLStreamException
case XML_START_ELEMENT:
System.out.printf(" XmlTokenStream.next(): XML_START_ELEMENT '%s' %s\n", _localName, _loc());
break;
case XML_DELAYED_START_ELEMENT:
System.out.printf(" XmlTokenStream.next(): XML_DELAYED_START_ELEMENT '%s' %s\n", _localName, _loc());
break;
case XML_END_ELEMENT:
// 24-May-2020, tatu: no name available for end element so do not print
System.out.printf(" XmlTokenStream.next(): XML_END_ELEMENT %s\n", _loc());
Expand Down Expand Up @@ -406,6 +403,16 @@ protected void pushbackCurrentToken()
_repeatCurrentToken = true;
}

/**
* Method that can be called to mark stream as having reached end of stream.
*
* @since 2.19
*/
protected void markAsStreamEnd()
{
_currentState = XML_END;
}

/**
* Method called to skip any attributes current START_ELEMENT may have,
* so that they are not returned as token.
Expand Down Expand Up @@ -460,6 +467,7 @@ private final int _next() throws XMLStreamException
// 08-Jul-2021, tatu: as per [dataformat-xml#467] just skip anything
// element might have, no need to ensure it was empty
_xmlReader.skipElement();
//System.out.println(" XmlTokenStream._next(): Got xsi:nil, skipping element");
return _handleEndElement();
}
if (_nextAttributeIndex < _attributeCount) {
Expand Down Expand Up @@ -693,7 +701,7 @@ private final void _checkXsiAttributes() {
int count = _xmlReader.getAttributeCount();
_attributeCount = count;

// [dataformat-xml#354]: xsi:nul handling; at first only if first attribute
// [dataformat-xml#354]: xsi:nil handling; at first only if first attribute
if (count >= 1) {
// [dataformat-xml#468]: may disable xsi:nil processing
if (_cfgProcessXsiNil
Expand All @@ -703,6 +711,7 @@ private final void _checkXsiAttributes() {
_nextAttributeIndex = 1;
// but only mark as nil marker if enabled
_xsiNilFound = "true".equals(_xmlReader.getAttributeValue(0));
//System.out.println(" XMLTokenStream._checkXsiAttributes(), _xsiNilFound: "+_xsiNilFound);
return;
}
}
Expand Down Expand Up @@ -813,6 +822,8 @@ private final int _handleEndElement()

}
} else {
//System.out.println(" XMLTokenStream._handleEndElement(): no wrapper");

// Not (necessarily) known, as per above, so:
_localName = "";
_namespaceURI = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.XmlTestUtil;
import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser;
import com.fasterxml.jackson.dataformat.xml.testutil.failure.JacksonTestFailureExpected;

import static org.junit.jupiter.api.Assertions.*;

Expand All @@ -22,7 +21,6 @@ public class XsiNilBasic714Test extends XmlTestUtil
.build();

// [dataformat-xml#714]: trailing END_OBJECT
@JacksonTestFailureExpected
@Test
public void testRootPojoAsNull() throws Exception
{
Expand All @@ -35,7 +33,6 @@ public void testRootPojoAsNull() throws Exception
// [dataformat-xml#468]: Allow disabling xsi:nil special handling

// [dataformat-xml#714]: trailing END_OBJECT
@JacksonTestFailureExpected
@Test
public void testDisableXsiNilRootProcessing() throws Exception
{
Expand All @@ -46,10 +43,12 @@ public void testDisableXsiNilRootProcessing() throws Exception
assertEquals("null", r.readValue(DOC).toString());

// 07-Jul-2021, tatu: Alas! 2.x sets format feature flags too late to
// affect root element (3.0 works correctly). So cannot test

ObjectReader noXsiNilReader = r.without(FromXmlParser.Feature.PROCESS_XSI_NIL);
// affect root element (3.0 works correctly). Need a new mapper
XmlMapper mapper2 = mapperBuilder()
.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.disable(FromXmlParser.Feature.PROCESS_XSI_NIL)
.build();
assertEquals(a2q("{'nil':'true'}"),
noXsiNilReader.readValue(DOC).toString());
mapper2.readerFor(JsonNode.class).readValue(DOC).toString());
}
}