Skip to content

Commit

Permalink
Fix #393
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed May 12, 2020
1 parent d07230f commit 6408a68
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 41 deletions.
3 changes: 2 additions & 1 deletion release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Project: jackson-dataformat-xml

2.11.1 (not yet released)

-
#393: `MismatchedInputException` for nested repeating element name in `List`
(reported by kaizenHorse@github)

2.11.0 (26-Apr-2020)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private Feature(boolean defaultState) {
*<p>
* Name used for pseudo-property used for returning XML Text value (which does
* not have actual element name to use). Defaults to empty String, but
* may be changed for interoperability reasons: JAXB, for example, uses
* may be changed for inter-operability reasons: JAXB, for example, uses
* "value" as name.
*
* @since 2.1
Expand Down Expand Up @@ -146,8 +146,6 @@ private Feature(boolean defaultState) {

protected String _currText;

protected Set<String> _namesToWrap;

/*
/**********************************************************
/* Parsing state, parsed values
Expand Down Expand Up @@ -323,14 +321,14 @@ public XMLStreamReader getStaxReader() {
*/
public void addVirtualWrapping(Set<String> namesToWrap)
{
/* 17-Sep-2012, tatu: Not 100% sure why, but this is necessary to avoid
* problems with Lists-in-Lists properties
*/
//System.out.println("addVirtualWrapping("+namesToWrap+")");
// 17-Sep-2012, tatu: Not 100% sure why, but this is necessary to avoid
// problems with Lists-in-Lists properties
String name = _xmlTokens.getLocalName();
if (name != null && namesToWrap.contains(name)) {
//System.out.println("REPEAT from addVirtualWrapping()");
_xmlTokens.repeatStartElement();
}
_namesToWrap = namesToWrap;
_parsingContext.setNamesToWrap(namesToWrap);
}

Expand Down Expand Up @@ -435,7 +433,7 @@ public boolean isExpectedStartArrayToken()
_currToken = JsonToken.START_ARRAY;
// Ok: must replace current context with array as well
_parsingContext.convertToArray();
//System.out.println(" isExpectedArrayStart: OBJ->Array, wraps now: "+_parsingContext.getNamesToWrap());
//System.out.println(" FromXmlParser.isExpectedArrayStart(): OBJ->Array");
// And just in case a field name was to be returned, wipe it
// 06-Jan-2015, tatu: Actually, could also be empty Object buffered; if so, convert...
if (_nextToken == JsonToken.END_OBJECT) {
Expand All @@ -460,13 +458,13 @@ public JsonToken nextToken() throws IOException
if (t != null) {
switch (t) {
case FIELD_NAME:
System.out.println("JsonToken: FIELD_NAME '"+_parsingContext.getCurrentName()+"'");
System.out.println("FromXmlParser.nextToken(): JsonToken.FIELD_NAME '"+_parsingContext.getCurrentName()+"'");
break;
case VALUE_STRING:
System.out.println("JsonToken: VALUE_STRING '"+getText()+"'");
System.out.println("FromXmlParser.nextToken(): JsonToken.VALUE_STRING '"+getText()+"'");
break;
default:
System.out.println("JsonToken: "+t);
System.out.println("FromXmlParser.nextToken(): "+t);
}
}
return t;
Expand All @@ -492,7 +490,6 @@ public JsonToken nextToken() throws IOException
case END_OBJECT:
case END_ARRAY:
_parsingContext = _parsingContext.getParent();
_namesToWrap = _parsingContext.getNamesToWrap();
break;
case FIELD_NAME:
_parsingContext.setCurrentName(_xmlTokens.getLocalName());
Expand Down Expand Up @@ -534,7 +531,8 @@ public JsonToken nextToken() throws IOException

// Ok: virtual wrapping can be done by simply repeating current START_ELEMENT.
// Couple of ways to do it; but start by making _xmlTokens replay the thing...
if (_namesToWrap != null && _namesToWrap.contains(name)) {
if (_parsingContext.shouldWrap(name)) {
//System.out.println("REPEAT from nextToken()");
_xmlTokens.repeatStartElement();
}

Expand Down Expand Up @@ -565,7 +563,6 @@ public JsonToken nextToken() throws IOException
}
_currToken = _parsingContext.inArray() ? JsonToken.END_ARRAY : JsonToken.END_OBJECT;
_parsingContext = _parsingContext.getParent();
_namesToWrap = _parsingContext.getNamesToWrap();
return _currToken;

case XmlTokenStream.XML_ATTRIBUTE_NAME:
Expand Down Expand Up @@ -696,7 +693,8 @@ public String nextTextValue() throws IOException
}
String name = _xmlTokens.getLocalName();
_parsingContext.setCurrentName(name);
if (_namesToWrap != null && _namesToWrap.contains(name)) {
if (_parsingContext.shouldWrap(name)) {
//System.out.println("REPEAT from nextTextValue()");
_xmlTokens.repeatStartElement();
}
_mayBeLeaf = true;
Expand All @@ -715,7 +713,6 @@ public String nextTextValue() throws IOException
}
_currToken = _parsingContext.inArray() ? JsonToken.END_ARRAY : JsonToken.END_OBJECT;
_parsingContext = _parsingContext.getParent();
_namesToWrap = _parsingContext.getNamesToWrap();
break;
case XmlTokenStream.XML_ATTRIBUTE_NAME:
// If there was a chance of leaf node, no more...
Expand Down Expand Up @@ -774,7 +771,6 @@ private void _updateState(JsonToken t)
case END_OBJECT:
case END_ARRAY:
_parsingContext = _parsingContext.getParent();
_namesToWrap = _parsingContext.getNamesToWrap();
break;
case FIELD_NAME:
_parsingContext.setCurrentName(_xmlTokens.getLocalName());
Expand Down Expand Up @@ -835,7 +831,6 @@ public String getValueAsString(String defValue) throws IOException
// note: Should NOT update context, because we will still be getting
// matching END_OBJECT, which will undo contexts properly
_parsingContext = _parsingContext.getParent();
_namesToWrap = _parsingContext.getNamesToWrap();
_currToken = JsonToken.VALUE_STRING;
_nextToken = null;
// One more thing: must explicitly skip the END_OBJECT that would follow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,16 @@ public void setNamesToWrap(Set<String> namesToWrap) {
_namesToWrap = namesToWrap;
}

public Set<String> getNamesToWrap() {
@Deprecated // since 2.11.1
public Set<String> getNamesToWrap() {
return _namesToWrap;
}

// @since 2.11.1
public boolean shouldWrap(String localName) {
return (_namesToWrap != null) && _namesToWrap.contains(localName);
}

protected void convertToArray() {
_type = TYPE_ARRAY;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,22 +170,22 @@ public int next() throws XMLStreamException
int n = next0();
switch (n) {
case XML_START_ELEMENT:
System.out.println(" XML-token: XML_START_ELEMENT '"+_localName+"'");
System.out.println(" XmlTolenStream.next(): XML_START_ELEMENT '"+_localName+"'");
break;
case XML_END_ELEMENT:
System.out.println(" XML-token: XML_END_ELEMENT '"+_localName+"'");
System.out.println(" XmlTolenStream.next(): XML_END_ELEMENT '"+_localName+"'");
break;
case XML_ATTRIBUTE_NAME:
System.out.println(" XML-token: XML_ATTRIBUTE_NAME '"+_localName+"'");
System.out.println(" XmlTolenStream.next(): XML_ATTRIBUTE_NAME '"+_localName+"'");
break;
case XML_ATTRIBUTE_VALUE:
System.out.println(" XML-token: XML_ATTRIBUTE_VALUE '"+_textValue+"'");
System.out.println(" XmlTolenStream.next(): XML_ATTRIBUTE_VALUE '"+_textValue+"'");
break;
case XML_TEXT:
System.out.println(" XML-token: XML_TEXT '"+_textValue+"'");
System.out.println(" XmlTolenStream.next(): XML_TEXT '"+_textValue+"'");
break;
case XML_END:
System.out.println(" XML-token: XML_END");
System.out.println(" XmlTolenStream.next(): XML_END");
break;
default:
throw new IllegalStateException();
Expand All @@ -194,7 +194,8 @@ public int next() throws XMLStreamException
}
*/

public int next() throws XMLStreamException
// public int next0() throws XMLStreamException
public int next() throws XMLStreamException
{
if (_repeatElement != 0) {
return (_currentState = _handleRepeatElement());
Expand Down Expand Up @@ -256,18 +257,19 @@ public JsonLocation getTokenLocation() {
*/
protected void repeatStartElement()
{
//System.out.println(" -> repeatStartElement for "+_localName);
//System.out.println(" -> repeatStartElement for "+_localName+", _currentWrapper was: "+_currentWrapper);
// sanity check: can only be used when just returned START_ELEMENT:
if (_currentState != XML_START_ELEMENT) {
throw new IllegalStateException("Current state not XML_START_ELEMENT ("
+XML_START_ELEMENT+") but "+_currentState);
}
// Important: add wrapper, to keep track...
if (_currentWrapper == null) {
_currentWrapper = ElementWrapper.matchingWrapper(_currentWrapper, _localName, _namespaceURI);
_currentWrapper = ElementWrapper.matchingWrapper(null, _localName, _namespaceURI);
} else {
_currentWrapper = ElementWrapper.matchingWrapper(_currentWrapper.getParent(), _localName, _namespaceURI);
}
//System.out.println(" repeatStartElement for "+_localName+", _currentWrapper now: "+_currentWrapper);
_repeatElement = REPLAY_START_DUP;
}

Expand Down Expand Up @@ -523,12 +525,13 @@ private final int _initStartElement() throws XMLStreamException
if (_currentWrapper != null) {
if (_currentWrapper.matchesWrapper(localName, ns)) {
_currentWrapper = _currentWrapper.intermediateWrapper();
//System.out.println(" _initStartElement(): START_ELEMENT ("+localName+") DOES match ["+_currentWrapper+"]: leave/add intermediate");
} else {
// implicit end is more interesting:
//System.out.println(" _initStartElement(): START_ELEMENT ("+localName+") not matching '"+_localName+"'; add extra XML-END-ELEMENT!");
_localName = _currentWrapper.getWrapperLocalName();
_namespaceURI = _currentWrapper.getWrapperNamespace();
_currentWrapper = _currentWrapper.getParent();
//System.out.println(" START_ELEMENT ("+localName+") not matching '"+_localName+"'; add extra XML-END-ELEMENT!");
// Important! We also need to restore the START_ELEMENT, so:
_nextLocalName = localName;
_nextNamespaceURI = ns;
Expand Down Expand Up @@ -571,16 +574,18 @@ private final void _checkXsiAttributes() {
*/
protected int _handleRepeatElement() throws XMLStreamException
{
//System.out.println(" XMLTokenStream._handleRepeatElement()");

int type = _repeatElement;
_repeatElement = 0;
if (type == REPLAY_START_DUP) {
//System.out.println("handleRepeat for START_ELEMENT: "+_localName+" ("+_xmlReader.getLocalName()+")");
//System.out.println(" XMLTokenStream._handleRepeatElement() for START_ELEMENT: "+_localName+" ("+_xmlReader.getLocalName()+")");
// important: add the virtual element second time, but not with name to match
_currentWrapper = _currentWrapper.intermediateWrapper();
return XML_START_ELEMENT;
}
if (type == REPLAY_END) {
//System.out.println("handleRepeat for END_ELEMENT: "+_localName+" ("+_xmlReader.getLocalName()+")");
//System.out.println(" XMLTokenStream._handleRepeatElement() for END_ELEMENT: "+_localName+" ("+_xmlReader.getLocalName()+")");
_localName = _xmlReader.getLocalName();
_namespaceURI = _xmlReader.getNamespaceURI();
if (_currentWrapper != null) {
Expand All @@ -596,8 +601,8 @@ protected int _handleRepeatElement() throws XMLStreamException
_namespaceURI = _nextNamespaceURI;
_nextLocalName = null;
_nextNamespaceURI = null;
//System.out.println("handleRepeat for START_DELAYED: "+_localName+" ("+_xmlReader.getLocalName()+")");

//System.out.println(" XMLTokenStream._handleRepeatElement() for START_DELAYED: "+_localName+" ("+_xmlReader.getLocalName()+")");

return XML_START_ELEMENT;
}
Expand All @@ -606,6 +611,7 @@ protected int _handleRepeatElement() throws XMLStreamException

private final int _handleEndElement()
{
//System.out.println(" XMLTokenStream._handleEndElement()");
if (_currentWrapper != null) {
ElementWrapper w = _currentWrapper;
// important: if we close the scope, must duplicate END_ELEMENT as well
Expand All @@ -614,7 +620,7 @@ private final int _handleEndElement()
_localName = w.getWrapperLocalName();
_namespaceURI = w.getWrapperNamespace();
_currentWrapper = _currentWrapper.getParent();
//System.out.println(" IMPLICIT requestRepeat of END_ELEMENT '"+_localName);
//System.out.println(" XMLTokenStream._handleEndElement(): IMPLICIT requestRepeat of END_ELEMENT '"+_localName);
} else {
_currentWrapper = _currentWrapper.getParent();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public Prices getPrices() {
}
}

// @JsonIgnoreProperties(ignoreUnknown = true)
@JacksonXmlRootElement(localName = "prices")
static class Prices {
private List<Price> price = new ArrayList<Price>();
Expand All @@ -38,14 +37,11 @@ public void setPrice(List<Price> price) {
}

@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "price")
public List<Price> getPrice() {
return this.price;
}
}

// @JacksonXmlRootElement(localName = "price")
// @JsonIgnoreProperties(ignoreUnknown = true)
static class Price {
private String price;
private String num;
Expand All @@ -60,7 +56,6 @@ public void setPrice(String price) {
this.price = price;
}

@JacksonXmlProperty(localName = "price")
public String getPrice() {
return this.price;
}
Expand All @@ -69,7 +64,6 @@ public void setNum(String num) {
this.num = num;
}

@JacksonXmlProperty(localName = "num")
public String getNum() {
return this.num;
}
Expand Down

0 comments on commit 6408a68

Please sign in to comment.