Skip to content

Commit 3da7073

Browse files
committed
More work on #405, token stream now includes text segments
1 parent d5237b0 commit 3da7073

File tree

4 files changed

+60
-29
lines changed

4 files changed

+60
-29
lines changed

src/main/java/com/fasterxml/jackson/dataformat/xml/deser/FromXmlParser.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ public JsonToken nextToken() throws IOException
645645
StaxUtil.throwAsParseException(e, this);
646646
}
647647
if (_parsingContext.inArray()) {
648-
if (_isEmpty(_currText)) {
648+
if (XmlTokenStream._allWs(_currText)) {
649649
// 06-Jan-2015, tatu: as per [dataformat-xml#180], need to
650650
// expose as empty Object, not null (or, worse, as used to
651651
// be done, by swallowing the token)
@@ -660,7 +660,7 @@ public JsonToken nextToken() throws IOException
660660
// but... [dataformat-xml#191]: looks like we can't short-cut, must
661661
// loop over again
662662
if (_parsingContext.inObject()) {
663-
if ((_currToken != JsonToken.FIELD_NAME) && _isEmpty(_currText)) {
663+
if ((_currToken != JsonToken.FIELD_NAME) && XmlTokenStream._allWs(_currText)) {
664664
try {
665665
token = _xmlTokens.next();
666666
} catch (XMLStreamException e) {
@@ -1094,19 +1094,6 @@ protected ByteArrayBuilder _getByteArrayBuilder()
10941094
return _byteArrayBuilder;
10951095
}
10961096

1097-
protected boolean _isEmpty(String str)
1098-
{
1099-
int len = (str == null) ? 0 : str.length();
1100-
if (len > 0) {
1101-
for (int i = 0; i < len; ++i) {
1102-
if (str.charAt(i) > ' ') {
1103-
return false;
1104-
}
1105-
}
1106-
}
1107-
return true;
1108-
}
1109-
11101097
private <T> T _internalErrorUnknownToken(Object token) {
11111098
throw new IllegalStateException("Internal error: unrecognized XmlTokenStream token: "+token);
11121099
}

src/main/java/com/fasterxml/jackson/dataformat/xml/deser/XmlTokenStream.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,11 @@ public class XmlTokenStream
7979
protected boolean _xsiNilFound;
8080

8181
/**
82-
* If true we have a START_ELEMENT with mixed text
82+
* Flag set true if current event is {@code XML_TEXT} and there is START_ELEMENT
8383
*
84-
* @since 2.8
84+
* @since 2.12
8585
*/
86-
protected boolean _mixedText;
86+
protected boolean _startElementAfterText;
8787

8888
/**
8989
* Index of the next attribute of the current START_ELEMENT
@@ -384,30 +384,30 @@ private final int _next() throws XMLStreamException
384384
final boolean startElementNext = _xmlReader.getEventType() == XMLStreamReader.START_ELEMENT;
385385
// If we have no/all-whitespace text followed by START_ELEMENT, ignore text
386386
if (startElementNext) {
387-
if (text == null || _allWs(text)) {
388-
_mixedText = false;
387+
if (_allWs(text)) {
388+
_startElementAfterText = false;
389389
return _initStartElement();
390390
}
391-
_mixedText = true;
391+
_startElementAfterText = true;
392392
_textValue = text;
393393
return (_currentState = XML_TEXT);
394394
}
395395
// For END_ELEMENT we will return text, if any
396396
if (text != null) {
397-
_mixedText = false;
397+
_startElementAfterText = false;
398398
_textValue = text;
399399
return (_currentState = XML_TEXT);
400400
}
401-
_mixedText = false;
401+
_startElementAfterText = false;
402402
return _handleEndElement();
403403

404404
case XML_ATTRIBUTE_NAME:
405405
// if we just returned name, will need to just send value next
406406
return (_currentState = XML_ATTRIBUTE_VALUE);
407407
case XML_TEXT:
408408
// mixed text with other elements
409-
if (_mixedText) {
410-
_mixedText = false;
409+
if (_startElementAfterText) {
410+
_startElementAfterText = false;
411411
return _initStartElement();
412412
}
413413
// text followed by END_ELEMENT
@@ -422,8 +422,19 @@ private final int _next() throws XMLStreamException
422422
case XMLStreamConstants.END_DOCUMENT:
423423
return (_currentState = XML_END);
424424
case XMLStreamConstants.END_ELEMENT:
425+
// 24-May-2020, tatu: Need to see if we have "mixed content" to offer
426+
if (!_allWs(_textValue)) {
427+
// _textValue already set
428+
return (_currentState = XML_TEXT);
429+
}
425430
return _handleEndElement();
426431
}
432+
// 24-May-2020, tatu: Need to see if we have "mixed content" to offer
433+
if (!_allWs(_textValue)) {
434+
// _textValue already set
435+
_startElementAfterText = true;
436+
return (_currentState = XML_TEXT);
437+
}
427438

428439
// START_ELEMENT...
429440
return _initStartElement();
@@ -697,7 +708,7 @@ private JsonLocation _extractLocation(XMLStreamLocation2 location)
697708
location.getColumnNumber());
698709
}
699710

700-
protected boolean _allWs(String str)
711+
protected static boolean _allWs(String str)
701712
{
702713
final int len = (str == null) ? 0 : str.length();
703714
if (len > 0) {

src/test/java/com/fasterxml/jackson/dataformat/xml/stream/XmlParserTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,15 @@ public void testXmlAttributes() throws Exception
251251
xp.close();
252252
}
253253

254+
public void testMixedContent() throws Exception
255+
{
256+
String exp = a2q("{'':'first','a':'123','':'second','b':'456','':'last'}");
257+
String result = _readXmlWriteJson("<root>first<a>123</a>second<b>456</b>last</root>");
258+
259+
//System.err.println("result = \n"+result);
260+
assertEquals(exp, result);
261+
}
262+
254263
/*
255264
/**********************************************************
256265
/* Helper methods

src/test/java/com/fasterxml/jackson/dataformat/xml/stream/XmlTokenStreamTest.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ public void testNested() throws Exception
129129
}
130130

131131
// For [dataformat-xml#402]
132-
/* public void testMixedContent() throws Exception
132+
public void testMixedContentBetween() throws Exception
133133
{
134-
String XML = "<root>first<a>123</a> and second <b>abc</b>last &amp; final</root>";
134+
String XML = "<root>first<a>123</a> and second <b>abc</b>\n</root>";
135135
XMLStreamReader sr = _staxInputFactory.createXMLStreamReader(new StringReader(XML));
136136
sr.nextTag();
137137
XmlTokenStream tokens = new XmlTokenStream(sr, XML, FromXmlParser.Feature.collectDefaults());
@@ -157,12 +157,36 @@ public void testNested() throws Exception
157157
assertEquals("abc", tokens.getText());
158158
assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next());
159159

160+
assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next());
161+
assertEquals(XmlTokenStream.XML_END, tokens.next());
162+
sr.close();
163+
}
164+
165+
// For [dataformat-xml#402]
166+
public void testMixedContentAfter() throws Exception
167+
{
168+
String XML = "<root>first<a>123</a>last &amp; final</root>";
169+
XMLStreamReader sr = _staxInputFactory.createXMLStreamReader(new StringReader(XML));
170+
sr.nextTag();
171+
XmlTokenStream tokens = new XmlTokenStream(sr, XML, FromXmlParser.Feature.collectDefaults());
172+
173+
assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.getCurrentToken());
174+
assertEquals("root", tokens.getLocalName());
175+
176+
assertEquals(XmlTokenStream.XML_TEXT, tokens.next());
177+
assertEquals("first", tokens.getText());
178+
179+
assertEquals(XmlTokenStream.XML_START_ELEMENT, tokens.next());
180+
assertEquals("a", tokens.getLocalName());
181+
assertEquals(XmlTokenStream.XML_TEXT, tokens.next());
182+
assertEquals("123", tokens.getText());
183+
assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next());
184+
160185
assertEquals(XmlTokenStream.XML_TEXT, tokens.next());
161186
assertEquals("last & final", tokens.getText());
162187

163188
assertEquals(XmlTokenStream.XML_END_ELEMENT, tokens.next());
164189
assertEquals(XmlTokenStream.XML_END, tokens.next());
165190
sr.close();
166191
}
167-
*/
168192
}

0 commit comments

Comments
 (0)