24
24
import javax .xml .stream .events .StartElement ;
25
25
26
26
import org .codehaus .stax2 .ri .typed .AsciiValueEncoder ;
27
+ import org .codehaus .stax2 .validation .XMLValidationException ;
28
+ import org .codehaus .stax2 .validation .XMLValidationSchema ;
29
+ import org .codehaus .stax2 .validation .XMLValidator ;
27
30
28
31
import com .ctc .wstx .api .EmptyElementHandler ;
29
32
import com .ctc .wstx .api .WriterConfig ;
33
+ import com .ctc .wstx .api .WstxInputProperties ;
30
34
import com .ctc .wstx .cfg .ErrorConsts ;
31
- import com .ctc .wstx .cfg .XmlConsts ;
32
35
import com .ctc .wstx .exc .WstxIOException ;
33
36
import com .ctc .wstx .util .DefaultXmlSymbolTable ;
34
37
@@ -246,9 +249,6 @@ public void writeEmptyElement(String localName)
246
249
throws XMLStreamException
247
250
{
248
251
checkStartElement (localName , null );
249
- if (mValidator != null ) {
250
- mValidator .validateElementStart (localName , XmlConsts .ELEM_NO_NS_URI , XmlConsts .ELEM_NO_PREFIX );
251
- }
252
252
mEmptyElement = true ;
253
253
if (mOutputElemPool != null ) {
254
254
SimpleOutputElement newCurr = mOutputElemPool ;
@@ -294,9 +294,6 @@ public void writeStartElement(String localName)
294
294
throws XMLStreamException
295
295
{
296
296
checkStartElement (localName , null );
297
- if (mValidator != null ) {
298
- mValidator .validateElementStart (localName , XmlConsts .ELEM_NO_NS_URI , XmlConsts .ELEM_NO_PREFIX );
299
- }
300
297
mEmptyElement = false ;
301
298
if (mOutputElemPool != null ) {
302
299
SimpleOutputElement newCurr = mOutputElemPool ;
@@ -334,19 +331,19 @@ protected void writeTypedAttribute(String prefix, String nsURI, String localName
334
331
if (!mStartElementOpen ) {
335
332
throwOutputError (ErrorConsts .WERR_ATTR_NO_ELEM );
336
333
}
337
- if (mCheckAttrs ) { // still need to ensure no duplicate attrs?
338
- mCurrElem .checkAttrWrite (nsURI , localName );
339
- }
340
334
try {
341
335
if (mValidator == null ) {
336
+ if (mCheckAttrs ) { // still need to ensure no duplicate attrs?
337
+ mCurrElem .addAttribute (nsURI , localName , null , null );
338
+ }
342
339
if (prefix == null || prefix .length () == 0 ) {
343
340
mWriter .writeTypedAttribute (localName , enc );
344
341
} else {
345
342
mWriter .writeTypedAttribute (prefix , localName , enc );
346
343
}
347
344
} else {
348
345
mWriter .writeTypedAttribute
349
- (prefix , localName , nsURI , enc , mValidator , getCopyBuffer ());
346
+ (prefix , localName , nsURI , enc , mCurrElem . getAttributeCollector () , getCopyBuffer ());
350
347
}
351
348
} catch (IOException ioe ) {
352
349
throw new WstxIOException (ioe );
@@ -430,7 +427,16 @@ protected void closeStartElement(boolean emptyElem)
430
427
}
431
428
432
429
if (mValidator != null ) {
433
- mVldContent = mValidator .validateElementAndAttributes ();
430
+ try {
431
+ mVldContent = mCurrElem .validateElementStartAndAttributes ();
432
+ if (emptyElem ) {
433
+ mVldContent = mValidator .validateElementEnd
434
+ (mCurrElem .getLocalName (), mCurrElem .getNamespaceURI (), mCurrElem .getPrefix ());
435
+ }
436
+ } catch (XMLValidationException e ) {
437
+ mVldException = e ;
438
+ throw e ;
439
+ }
434
440
}
435
441
436
442
// Need bit more special handling for empty elements...
@@ -440,10 +446,6 @@ protected void closeStartElement(boolean emptyElem)
440
446
if (mCurrElem .isRoot ()) { // Did we close the root? (isRoot() returns true for the virtual "document node")
441
447
mState = STATE_EPILOG ;
442
448
}
443
- if (mValidator != null ) {
444
- mVldContent = mValidator .validateElementEnd
445
- (curr .getLocalName (), curr .getNamespaceURI (), curr .getPrefix ());
446
- }
447
449
if (mPoolSize < MAX_POOL_SIZE ) {
448
450
curr .addToPool (mOutputElemPool );
449
451
mOutputElemPool = curr ;
@@ -471,6 +473,9 @@ protected String getTopElementDesc() {
471
473
protected void checkStartElement (String localName , String prefix )
472
474
throws XMLStreamException
473
475
{
476
+ if (mVldException != null ) {
477
+ throw new XMLStreamException ("Cannot start an element after a validation error" , mVldException );
478
+ }
474
479
// Need to finish an open start element?
475
480
if (mStartElementOpen ) {
476
481
closeStartElement (mEmptyElement );
@@ -493,13 +498,14 @@ protected final void doWriteAttr(String localName, String nsURI, String prefix,
493
498
String value )
494
499
throws XMLStreamException
495
500
{
496
- if (mCheckAttrs ) { // still need to ensure no duplicate attrs?
497
- mCurrElem .checkAttrWrite (nsURI , localName );
498
- }
499
- if (mValidator != null ) {
500
- // No need to get it normalized... even if validator does normalize
501
- // it, we don't use that for anything
502
- mValidator .validateAttribute (localName , nsURI , prefix , value );
501
+ if (mCheckAttrs ) {
502
+ // ensure no duplicate attrs and possibly pass them to validator when closing the start element
503
+ try {
504
+ mCurrElem .addAttribute (nsURI , localName , prefix , value );
505
+ } catch (XMLValidationException e ) {
506
+ mVldException = e ;
507
+ throw e ;
508
+ }
503
509
}
504
510
try {
505
511
int vlen = value .length ();
@@ -532,29 +538,6 @@ protected final void doWriteAttr(String localName, String nsURI, String prefix,
532
538
}
533
539
}
534
540
535
- protected final void doWriteAttr (String localName , String nsURI , String prefix ,
536
- char [] buf , int start , int len )
537
- throws XMLStreamException
538
- {
539
- if (mCheckAttrs ) { // still need to ensure no duplicate attrs?
540
- mCurrElem .checkAttrWrite (nsURI , localName );
541
- }
542
- if (mValidator != null ) {
543
- // No need to get it normalized... even if validator does normalize
544
- // it, we don't use that for anything
545
- mValidator .validateAttribute (localName , nsURI , prefix , buf , start , len );
546
- }
547
- try {
548
- if (prefix != null && prefix .length () > 0 ) {
549
- mWriter .writeAttribute (prefix , localName , buf , start , len );
550
- } else {
551
- mWriter .writeAttribute (localName , buf , start , len );
552
- }
553
- } catch (IOException ioe ) {
554
- throw new WstxIOException (ioe );
555
- }
556
- }
557
-
558
541
protected void doWriteNamespace (String prefix , String nsURI )
559
542
throws XMLStreamException
560
543
{
@@ -653,11 +636,28 @@ protected void doWriteEndTag(QName expName, boolean allowEmpty)
653
636
}
654
637
655
638
// Better have something to close... (to figure out what to close)
656
- if (mState != STATE_TREE ) {
639
+ if (mVldException != null ) {
640
+ throw new XMLStreamException ("Cannot start an element after a validation error" , mVldException );
641
+ } else if (mState != STATE_TREE ) {
657
642
// Have to always throw exception... don't necessarily know the name
658
643
reportNwfStructure ("No open start element, when trying to write end element" );
659
644
}
660
645
646
+ if (mStartElementOpen ) {
647
+ if (mValidator != null ) {
648
+ // We need to validate here, before we move the mCurrElem
649
+ try {
650
+ /* Note: return value is not of much use, since the
651
+ * element will be closed right away...
652
+ */
653
+ mVldContent = mCurrElem .validateElementStartAndAttributes ();
654
+ } catch (XMLValidationException e ) {
655
+ mVldException = e ;
656
+ throw e ;
657
+ }
658
+ }
659
+ }
660
+
661
661
SimpleOutputElement thisElem = mCurrElem ;
662
662
String prefix = thisElem .getPrefix ();
663
663
String localName = thisElem .getLocalName ();
@@ -691,12 +691,6 @@ protected void doWriteEndTag(QName expName, boolean allowEmpty)
691
691
/* Can't/shouldn't call closeStartElement, but need to do same
692
692
* processing. Thus, this is almost identical to closeStartElement:
693
693
*/
694
- if (mValidator != null ) {
695
- /* Note: return value is not of much use, since the
696
- * element will be closed right away...
697
- */
698
- mVldContent = mValidator .validateElementAndAttributes ();
699
- }
700
694
mStartElementOpen = false ;
701
695
try {
702
696
//If an EmptyElementHandler is provided use it to determine if allowEmpty is set
@@ -710,7 +704,12 @@ protected void doWriteEndTag(QName expName, boolean allowEmpty)
710
704
mState = STATE_EPILOG ;
711
705
}
712
706
if (mValidator != null ) {
713
- mVldContent = mValidator .validateElementEnd (localName , nsURI , prefix );
707
+ try {
708
+ mVldContent = mValidator .validateElementEnd (localName , nsURI , prefix );
709
+ } catch (XMLValidationException e ) {
710
+ mVldException = e ;
711
+ throw e ;
712
+ }
714
713
}
715
714
return ;
716
715
}
@@ -733,7 +732,12 @@ protected void doWriteEndTag(QName expName, boolean allowEmpty)
733
732
734
733
// Ok, time to validate...
735
734
if (mValidator != null ) {
736
- mVldContent = mValidator .validateElementEnd (localName , nsURI , prefix );
735
+ try {
736
+ mVldContent = mValidator .validateElementEnd (localName , nsURI , prefix );
737
+ } catch (XMLValidationException e ) {
738
+ mVldException = e ;
739
+ throw e ;
740
+ }
737
741
}
738
742
}
739
743
@@ -763,4 +767,96 @@ protected abstract void writeStartOrEmpty(String localName, String nsURI)
763
767
764
768
protected abstract void writeStartOrEmpty (String prefix , String localName , String nsURI )
765
769
throws XMLStreamException ;
770
+
771
+ /*
772
+ ///////////////////////////////////////////////////////////////////////
773
+ // Attribute access
774
+ ///////////////////////////////////////////////////////////////////////
775
+ */
776
+
777
+ @ Override
778
+ public int getAttributeCount ()
779
+ {
780
+ return mCurrElem .getAttributeCount ();
781
+ }
782
+
783
+ @ Override
784
+ public String getAttributeLocalName (int index )
785
+ {
786
+ return mCurrElem .getAttributeLocalName (index );
787
+ }
788
+
789
+ @ Override
790
+ public String getAttributeNamespace (int index )
791
+ {
792
+ return mCurrElem .getAttributeNamespace (index );
793
+ }
794
+
795
+ @ Override
796
+ public String getAttributePrefix (int index )
797
+ {
798
+ return mCurrElem .getAttributePrefix (index );
799
+ }
800
+
801
+ @ Override
802
+ public String getAttributeValue (int index )
803
+ {
804
+ return mCurrElem .getAttributeValue (index );
805
+ }
806
+
807
+ @ Override
808
+ public String getAttributeValue (String nsURI , String localName )
809
+ {
810
+ return mCurrElem .getAttributeValue (nsURI , localName );
811
+ }
812
+
813
+ @ Override
814
+ public String getAttributeType (int index ) {
815
+ return (mValidator == null ) ? WstxInputProperties .UNKNOWN_ATTR_TYPE :
816
+ mValidator .getAttributeType (index );
817
+ }
818
+
819
+ @ Override
820
+ public int findAttributeIndex (String nsURI , String localName )
821
+ {
822
+ return mCurrElem .findAttributeIndex (nsURI , localName );
823
+ }
824
+
825
+ /*
826
+ ///////////////////////////////////////////////////////////////////////
827
+ // Overrides to keep the validator up to date in SimpleOutputElement instances
828
+ ///////////////////////////////////////////////////////////////////////
829
+ */
830
+
831
+ @ Override
832
+ public XMLValidator validateAgainst (XMLValidationSchema schema ) throws XMLStreamException {
833
+ final XMLValidator validateAgainst = super .validateAgainst (schema );
834
+ mCurrElem .setValidator (mValidator );
835
+ if (mOutputElemPool != null ) {
836
+ mOutputElemPool .setValidator (mValidator );
837
+ }
838
+ return validateAgainst ;
839
+ }
840
+
841
+ @ Override
842
+ public XMLValidator stopValidatingAgainst (XMLValidationSchema schema ) throws XMLStreamException {
843
+ final XMLValidator result = super .stopValidatingAgainst (schema );
844
+ mCurrElem .setValidator (mValidator );
845
+ if (mOutputElemPool != null ) {
846
+ mOutputElemPool .setValidator (mValidator );
847
+ }
848
+ return result ;
849
+ }
850
+
851
+ @ Override
852
+ public XMLValidator stopValidatingAgainst (XMLValidator validator ) throws XMLStreamException {
853
+ final XMLValidator result = super .stopValidatingAgainst (validator );
854
+ mCurrElem .setValidator (mValidator );
855
+ if (mOutputElemPool != null ) {
856
+ mOutputElemPool .setValidator (mValidator );
857
+ }
858
+ return result ;
859
+ }
860
+
861
+
766
862
}
0 commit comments