1
1
package com .fasterxml .jackson .dataformat .xml .deser ;
2
2
3
3
import java .io .IOException ;
4
+ import java .util .Objects ;
4
5
5
6
import javax .xml .XMLConstants ;
7
+ import javax .xml .namespace .QName ;
6
8
import javax .xml .stream .*;
7
9
10
+ import com .fasterxml .jackson .dataformat .xml .ser .ToXmlGenerator ;
8
11
import org .codehaus .stax2 .XMLStreamLocation2 ;
9
12
import org .codehaus .stax2 .XMLStreamReader2 ;
10
13
import org .codehaus .stax2 .ri .Stax2ReaderAdapter ;
@@ -73,6 +76,8 @@ public class XmlTokenStream
73
76
74
77
protected boolean _cfgProcessXsiNil ;
75
78
79
+ protected boolean _cfgProcessEscapedTag ;
80
+
76
81
/*
77
82
/**********************************************************************
78
83
/* Parsing state
@@ -158,6 +163,7 @@ public XmlTokenStream(XMLStreamReader xmlReader, ContentReference sourceRef,
158
163
_sourceReference = sourceRef ;
159
164
_formatFeatures = formatFeatures ;
160
165
_cfgProcessXsiNil = FromXmlParser .Feature .PROCESS_XSI_NIL .enabledIn (_formatFeatures );
166
+ _cfgProcessEscapedTag = FromXmlParser .Feature .PROCESS_ESCAPED_MALFORMED_TAGS .enabledIn (_formatFeatures );
161
167
_xmlReader = Stax2ReaderAdapter .wrapIfNecessary (xmlReader );
162
168
}
163
169
@@ -176,7 +182,7 @@ public int initialize() throws XMLStreamException
176
182
_localName = _xmlReader .getLocalName ();
177
183
_namespaceURI = _xmlReader .getNamespaceURI ();
178
184
179
- _checkXsiAttributes (); // sets _attributeCount, _nextAttributeIndex
185
+ _checkMagicAttributes (); // sets _attributeCount, _nextAttributeIndex
180
186
181
187
// 02-Jul-2020, tatu: Two choices: if child elements OR attributes, expose
182
188
// as Object value; otherwise expose as Text
@@ -220,6 +226,7 @@ public XMLStreamReader2 getXmlReader() {
220
226
protected void setFormatFeatures (int f ) {
221
227
_formatFeatures = f ;
222
228
_cfgProcessXsiNil = FromXmlParser .Feature .PROCESS_XSI_NIL .enabledIn (f );
229
+ _cfgProcessEscapedTag = FromXmlParser .Feature .PROCESS_ESCAPED_MALFORMED_TAGS .enabledIn (f );
223
230
}
224
231
225
232
/*
@@ -618,17 +625,14 @@ private final String _getText(XMLStreamReader2 r) throws XMLStreamException
618
625
619
626
private final int _initStartElement () throws XMLStreamException
620
627
{
621
- final String ns = _xmlReader .getNamespaceURI ();
622
- final String localName = _xmlReader .getLocalName ();
623
-
624
- _checkXsiAttributes ();
628
+ final QName qName = _checkMagicAttributes ();
625
629
626
630
// Support for virtual wrapping: in wrapping, may either create a new
627
631
// wrapper scope (if in sub-tree, or matches wrapper element itself),
628
632
// or implicitly close existing scope.
629
633
630
634
if (_currentWrapper != null ) {
631
- if (_currentWrapper .matchesWrapper (localName , ns )) {
635
+ if (_currentWrapper .matchesWrapper (qName . getLocalPart (), qName . getNamespaceURI () )) {
632
636
_currentWrapper = _currentWrapper .intermediateWrapper ();
633
637
//System.out.println(" _initStartElement(): START_ELEMENT ("+localName+") DOES match ["+_currentWrapper+"]: leave/add intermediate");
634
638
} else {
@@ -638,23 +642,28 @@ private final int _initStartElement() throws XMLStreamException
638
642
_namespaceURI = _currentWrapper .getWrapperNamespace ();
639
643
_currentWrapper = _currentWrapper .getParent ();
640
644
// Important! We also need to restore the START_ELEMENT, so:
641
- _nextLocalName = localName ;
642
- _nextNamespaceURI = ns ;
645
+ _nextLocalName = qName . getLocalPart () ;
646
+ _nextNamespaceURI = qName . getNamespaceURI () ;
643
647
_repeatElement = REPLAY_START_DELAYED ;
644
648
return (_currentState = XML_END_ELEMENT );
645
649
}
646
650
}
647
- _localName = localName ;
648
- _namespaceURI = ns ;
651
+ _localName = qName . getLocalPart () ;
652
+ _namespaceURI = qName . getNamespaceURI () ;
649
653
return (_currentState = XML_START_ELEMENT );
650
654
}
651
655
652
656
/**
653
657
* @since 2.10
654
658
*/
655
- private final void _checkXsiAttributes () {
659
+ protected QName _checkMagicAttributes () {
656
660
int count = _xmlReader .getAttributeCount ();
657
661
_attributeCount = count ;
662
+ _nextAttributeIndex = 0 ;
663
+ _xsiNilFound = false ;
664
+
665
+ String ns = _xmlReader .getNamespaceURI ();
666
+ String localName = _xmlReader .getLocalName ();
658
667
659
668
// [dataformat-xml#354]: xsi:nul handling; at first only if first attribute
660
669
if (count >= 1 ) {
@@ -666,13 +675,21 @@ private final void _checkXsiAttributes() {
666
675
_nextAttributeIndex = 1 ;
667
676
// but only mark as nil marker if enabled
668
677
_xsiNilFound = "true" .equals (_xmlReader .getAttributeValue (0 ));
669
- return ;
670
678
}
671
679
}
672
680
}
673
681
674
- _nextAttributeIndex = 0 ;
675
- _xsiNilFound = false ;
682
+ // Handle PROCESS_ESCAPED_MALFORMED_TAGS
683
+ if (count > _nextAttributeIndex && _cfgProcessEscapedTag && localName .equals (ToXmlGenerator .ESCAPED_TAG_NAME )) {
684
+ final String attr = _xmlReader .getAttributeLocalName (_nextAttributeIndex );
685
+ final String attrNS = _xmlReader .getAttributeNamespace (_nextAttributeIndex );
686
+ if (Objects .equals (attrNS , ToXmlGenerator .ESCAPED_ATTR_NS ) && Objects .equals (attr , ToXmlGenerator .ESCAPED_ATTR_NAME )) {
687
+ localName = _xmlReader .getAttributeValue (_nextAttributeIndex );
688
+ _nextAttributeIndex += 1 ;
689
+ }
690
+ }
691
+
692
+ return new QName (ns , localName );
676
693
}
677
694
678
695
/**
0 commit comments