source: icXML/icXML-devel/src/icxercesc/internal/IGXMLScanner.cpp

Last change on this file was 3564, checked in by cameron, 6 years ago

Changes to icxercesc files

File size: 44.3 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: IGXMLScanner.cpp 882548 2009-11-20 13:44:14Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <icxercesc/internal/IGXMLScanner.hpp>
26#include <xercesc/util/RuntimeException.hpp>
27#include <xercesc/util/UnexpectedEOFException.hpp>
28#include <xercesc/sax/InputSource.hpp>
29#include <icxercesc/framework/XMLDocumentHandler.hpp>
30#include <xercesc/framework/XMLEntityHandler.hpp>
31#include <xercesc/framework/XMLPScanToken.hpp>
32#include <xercesc/framework/MemoryManager.hpp>
33#include <icxercesc/framework/XMLGrammarPool.hpp>
34#include <xercesc/framework/XMLDTDDescription.hpp>
35#include <xercesc/framework/psvi/PSVIElement.hpp>
36#include <xercesc/framework/psvi/PSVIHandler.hpp>
37#include <xercesc/framework/psvi/PSVIAttributeList.hpp>
38#include <icxercesc/validators/common/GrammarResolver.hpp>
39#include <xercesc/validators/DTD/DocTypeHandler.hpp>
40#include <icxercesc/validators/DTD/DTDScanner.hpp>
41#include <icxercesc/validators/DTD/DTDValidator.hpp>
42#include <icxercesc/validators/schema/SchemaValidator.hpp>
43#include <icxercesc/validators/schema/identity/IdentityConstraintHandler.hpp>
44#include <xercesc/validators/schema/identity/IC_Selector.hpp>
45#include <xercesc/util/OutOfMemoryException.hpp>
46#include <icxercesc/util/XMLString.hpp>
47#include <icxmlc/XMLNamespaceResolver.hpp>
48#include <icxmlc/XMLStringU.hpp>
49#ifdef USE_FAKE_VALIDATOR
50#include <xercesc/validators/FakeValidator.hpp>
51#endif
52
53XERCES_CPP_NAMESPACE_BEGIN
54
55typedef JanitorMemFunCall<IGXMLScanner> CleanupType;
56typedef JanitorMemFunCall<ReaderMgr>    ReaderMgrResetType;
57
58// ---------------------------------------------------------------------------
59//  IGXMLScanner: Constructors and Destructor
60// ---------------------------------------------------------------------------
61IGXMLScanner::IGXMLScanner( XMLValidator* const  valToAdopt
62                                                  , GrammarResolver* const grammarResolver
63                                                  , MemoryManager* const manager) :
64
65        XMLScanner(valToAdopt, grammarResolver, manager)
66        , fGrammarType(Grammar::UnKnown)
67        , fElemStateSize(16)
68        , fElemState(0)
69        , fElemLoopState(0)
70        , fWSNormalizeBuf(1023, manager)
71        , fDTDValidator(0)
72        , fSchemaValidator(0)
73        , fDTDGrammar(0)
74        , fICHandler(0)
75        , fDTDElemNonDeclPool(0)
76        , fSchemaElemNonDeclPool(0)
77        , fPSVIAttrList(0)
78        , fModel(0)
79        , fPSVIElement(0)
80        , fSchemaInfoList(0)
81        , fCachedSchemaInfoList (0)
82    , fAnySimpleTypeValidator(0)
83{
84        CleanupType cleanup(this, &IGXMLScanner::cleanUp);
85
86        try
87        {
88                commonInit();
89        }
90        catch(const OutOfMemoryException&)
91        {
92                // Don't cleanup when out of memory, since executing the
93                // code can cause problems.
94                cleanup.release();
95
96                throw;
97        }
98
99        cleanup.release();
100}
101
102IGXMLScanner::IGXMLScanner( XMLDocumentHandler* const docHandler
103                                                  , DocTypeHandler* const     docTypeHandler
104                                                  , XMLEntityHandler* const   entityHandler
105                                                  , XMLErrorReporter* const   errHandler
106                                                  , XMLValidator* const       valToAdopt
107                                                  , GrammarResolver* const    grammarResolver
108                                                  , MemoryManager* const      manager) :
109
110        XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager)
111        , fGrammarType(Grammar::UnKnown)
112        , fElemStateSize(16)
113        , fElemState(0)
114        , fElemLoopState(0)
115        , fWSNormalizeBuf(1023, manager)
116        , fDTDValidator(0)
117        , fSchemaValidator(0)
118        , fDTDGrammar(0)
119        , fICHandler(0)
120        , fDTDElemNonDeclPool(0)
121        , fSchemaElemNonDeclPool(0)
122        , fPSVIAttrList(0)
123        , fModel(0)
124        , fPSVIElement(0)
125        , fSchemaInfoList(0)
126        , fCachedSchemaInfoList (0)
127    , fAnySimpleTypeValidator(0)
128{
129        CleanupType cleanup(this, &IGXMLScanner::cleanUp);
130
131        try
132        {
133                commonInit();
134        }
135        catch(const OutOfMemoryException&)
136        {
137                // Don't cleanup when out of memory, since executing the
138                // code can cause problems.
139                cleanup.release();
140
141                throw;
142        }
143
144        cleanup.release();
145}
146
147IGXMLScanner::~IGXMLScanner()
148{
149        cleanUp();
150}
151
152// ---------------------------------------------------------------------------
153//  XMLScanner: Getter methods
154// ---------------------------------------------------------------------------
155NameIdPool<DTDEntityDecl>* IGXMLScanner::getEntityDeclPool()
156{
157        if(!fDTDGrammar)
158                return 0;
159        return fDTDGrammar->getEntityDeclPool();
160}
161
162const NameIdPool<DTDEntityDecl>* IGXMLScanner::getEntityDeclPool() const
163{
164        if(!fDTDGrammar)
165                return 0;
166        return fDTDGrammar->getEntityDeclPool();
167}
168
169// ---------------------------------------------------------------------------
170//  IGXMLScanner: Main entry point to scan a document
171// ---------------------------------------------------------------------------
172void IGXMLScanner::scanDocument( const InputSource & src )
173{
174        //  Bump up the sequence id for this parser instance. This will invalidate
175        //  any previous progressive scan tokens.
176        fSequenceId++;
177        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
178
179        try
180        {
181                //  Reset the scanner and its plugged in stuff for a new run. This
182                //  resets all the data structures, creates the initial reader and
183                //  pushes it on the stack, and sets up the base document path.
184                scanReset(src);
185
186                // If we have a document handler, then call the start document
187                if (fDocHandler)
188                        fDocHandler->startDocument();
189
190                if (fReaderMgr.getCurrentReader()->scanDocument<IGXMLScanner>(this))
191                {
192                        // Do post-parse validation if required
193                        if (fValidate)
194                        {
195                                //  We handle ID reference semantics at this level since
196                                //  its required by XML 1.0.
197                                checkIDRefs();
198                        }
199                }
200
201                // If we have a document handler, then call the end document
202                if (fDocHandler)
203                        fDocHandler->endDocument();
204        }
205        //  NOTE:
206        //
207        //  In all of the error processing below, the emitError() call MUST come
208        //  before the flush of the reader mgr, or it will fail because it tries
209        //  to find out the position in the XML source of the error.
210        catch(const XMLErrs::Codes)
211        {
212                // This is a 'first failure' exception, so fall through
213        }
214        catch(const XMLValid::Codes)
215        {
216                // This is a 'first fatal error' type exit, so fall through
217        }
218        catch(const XMLException& excToCatch)
219        {
220                //  Emit the error and catch any user exception thrown from here. Make
221                //  sure in all cases we flush the reader manager.
222                fInException = true;
223                try
224                {
225                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
226                                emitError
227                                (
228                                        XMLErrs::XMLException_Warning
229                                        , excToCatch.getCode()
230                                        , excToCatch.getMessage()
231                                );
232                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
233                                emitError
234                                (
235                                        XMLErrs::XMLException_Fatal
236                                        , excToCatch.getCode()
237                                        , excToCatch.getMessage()
238                                );
239                        else
240                                emitError
241                                (
242                                        XMLErrs::XMLException_Error
243                                        , excToCatch.getCode()
244                                        , excToCatch.getMessage()
245                                );
246                }
247                catch(const OutOfMemoryException&)
248                {
249                        // This is a special case for out-of-memory
250                        // conditions, because resetting the ReaderMgr
251                        // can be problematic.
252                        resetReaderMgr.release();
253
254                        throw;
255                }
256        }
257        catch(const OutOfMemoryException&)
258        {
259                // This is a special case for out-of-memory
260                // conditions, because resetting the ReaderMgr
261                // can be problematic.
262                resetReaderMgr.release();
263
264                throw;
265        }
266}
267
268void IGXMLScanner::scanFirst()
269{
270    fReaderMgr.getCurrentReader()->scanFirst<IGXMLScanner>(this);
271}
272
273bool IGXMLScanner::scanNext(XMLPScanToken & token)
274{
275        // Make sure this token is still legal
276    if (unlikely(!isLegalToken(token)))
277                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager);
278
279        try
280        {
281                // If we hit the end, then do the miscellaneous part
282        if (likely(fReaderMgr.getCurrentReader()->scanNext<IGXMLScanner>()))
283                {
284            return true;
285        }
286
287        // Do post-parse validation if required
288        if (fValidate)
289        {
290            //  We handle ID reference semantics at this level since
291            //  its required by XML 1.0.
292            checkIDRefs();
293        }
294
295        if (toCheckIdentityConstraint())
296            fICHandler->endDocument();
297
298        if (fDocHandler)
299            fDocHandler->endDocument();
300        }
301        catch(const XMLErrs::Codes)
302        {
303
304        }
305        catch(const XMLValid::Codes)
306        {
307
308        }
309        catch(const XMLException& excToCatch)
310        {
311                //  Emit the error and catch any user exception thrown from here. Make
312                //  sure in all cases we flush the reader manager.
313                fInException = true;
314                try
315                {
316                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
317                                emitError
318                                (
319                                        XMLErrs::XMLException_Warning
320                                        , excToCatch.getCode()
321                                        , excToCatch.getMessage()
322                                );
323                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
324                                emitError
325                                (
326                                        XMLErrs::XMLException_Fatal
327                                        , excToCatch.getCode()
328                                        , excToCatch.getMessage()
329                                );
330                        else
331                                emitError(XMLErrs::XMLException_Error, excToCatch.getCode(), excToCatch.getMessage());
332                }
333                catch(const OutOfMemoryException&)
334                {
335                        throw;
336                }
337        }
338        catch(const OutOfMemoryException&)
339        {
340                throw;
341        }
342
343        fReaderMgr.reset();
344
345        return false;
346}
347
348// ---------------------------------------------------------------------------
349//  IGXMLScanner: Private helper methods. Most of these are implemented in
350//  IGXMLScanner2.Cpp.
351// ---------------------------------------------------------------------------
352
353//  This method handles the common initialization, to avoid having to do
354//  it redundantly in multiple constructors.
355void IGXMLScanner::commonInit()
356{
357        //  Create the element state array
358        fElemState = (unsigned int*) fMemoryManager->allocate(fElemStateSize * sizeof(unsigned int)); 
359
360        fElemLoopState = (unsigned int*) fMemoryManager->allocate(fElemStateSize * sizeof(unsigned int)); //new unsigned int[fElemStateSize];
361
362    fDTDValidator = new (fMemoryManager) DTDValidator();
363        //  Create the Validator and init them
364    #ifdef USE_FAKE_VALIDATOR
365    fSchemaValidator = (SchemaValidator*)new (fMemoryManager) FakeSchemaValidator(0, fMemoryManager);
366    #else       
367        fSchemaValidator = new (fMemoryManager) SchemaValidator(0, fMemoryManager);
368    #endif
369
370    initValidator(fDTDValidator);
371    initValidator(fSchemaValidator);
372
373        // Create IdentityConstraint info
374    fICHandler = new (fMemoryManager) IdentityConstraintHandler(this, fGrammarResolver->getStringPool(), fMemoryManager);
375
376        // create pools for undeclared elements
377        fDTDElemNonDeclPool = new (fMemoryManager) NameIdPool<DTDElementDecl>(29, 128, fMemoryManager);
378    fSchemaElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool<SchemaElementDecl>(29, true, 128, fMemoryManager);
379
380        fSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf<SchemaInfo>(29, fMemoryManager);
381        fCachedSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf<SchemaInfo>(29, fMemoryManager);
382
383    fAnySimpleTypeValidator = 0;
384
385        // use fDTDValidator as the default validator
386        if (!fValidator)
387        {
388                fValidator = fDTDValidator;
389        }
390}
391
392void IGXMLScanner::setLocator(Locator * locator)
393{
394    fDTDValidator->setLocator(locator);
395    fSchemaValidator->setLocator(locator);
396}
397
398void IGXMLScanner::cleanUp()
399{
400        fMemoryManager->deallocate(fElemState);
401        fMemoryManager->deallocate(fElemLoopState);
402        delete fDTDValidator;
403        delete fSchemaValidator;
404        delete fICHandler;
405        delete fDTDElemNonDeclPool;
406        delete fSchemaElemNonDeclPool;
407        delete fPSVIAttrList;
408        delete fPSVIElement;
409        delete fSchemaInfoList;
410        delete fCachedSchemaInfoList;
411}
412
413// ---------------------------------------------------------------------------
414//  IGXMLScanner: Private Scanning Methods
415// ---------------------------------------------------------------------------
416
417//  This method handles the high level logic of scanning the DOCType
418//  declaration. This calls the DTDScanner and kicks off both the scanning of
419//  the internal subset and the scanning of the external subset, if any.
420//
421//  When we get here the '<!DOCTYPE' part has already been scanned, which is
422//  what told us that we had a doc type decl to parse.
423void IGXMLScanner::scanDocTypeDecl()
424{
425    //  We have a doc type. So, switch the Grammar.
426    switchGrammar(XMLNamespaceResolver::fEmptyUriId, XMLUni::fgDTDEntityString);
427    // setCurrentGrammar(fGrammarResolver->getGrammar(XMLUni::fgDTDEntityString));
428
429    if (fDocTypeHandler)
430        fDocTypeHandler->resetDocType();
431
432    // There must be some space after DOCTYPE
433    bool skippedSomething;
434    fReaderMgr.skipPastSpaces(skippedSomething);
435    if (!skippedSomething)
436    {
437        emitError(XMLErrs::ExpectedWhitespace);
438
439        // Just skip the Doctype declaration and return
440        fReaderMgr.skipPastChar(chCloseAngle);
441        return;
442    }
443
444    // Get a buffer for the root element
445    XMLBufBid bbRootName(&fBufMgr);
446
447    //  Get a name from the input, which should be the name of the root
448    //  element of the upcoming content.
449    int  colonPosition;
450    bool validName = fDoNamespaces ?
451            fReaderMgr.getQName(bbRootName.getBuffer(), &colonPosition) :
452            fReaderMgr.getName(bbRootName.getBuffer());
453
454    if (!validName)
455    {
456        if (bbRootName.isEmpty())
457            emitError(XMLErrs::NoRootElemInDOCTYPE);
458        else
459            emitError(XMLErrs::InvalidRootElemInDOCTYPE, bbRootName.getRawBuffer());
460        fReaderMgr.skipPastChar(chCloseAngle);
461        return;
462    }
463
464    //  This element obviously is not going to exist in the element decl
465    //  pool yet, but we need to call docTypeDecl. So force it into
466    //  the element decl pool, marked as being there because it was in
467    //  the DOCTYPE. Later, when its declared, the status will be updated.
468    //
469    //  Only do this if we are not reusing the validator! If we are reusing,
470    //  then look it up instead. It has to exist!
471    MemoryManager* const  rootDeclMgr =
472        fUseCachedGrammar ? fMemoryManager : fGrammarPoolMemoryManager;
473
474    DTDElementDecl* rootDecl = new (rootDeclMgr) DTDElementDecl
475    (
476        bbRootName.getRawBuffer()
477        , XMLNamespaceResolver::fEmptyUriId
478        , DTDElementDecl::Any
479        , fGrammarResolver->getStringPool()
480    );
481
482    //  Store the root element name for later check
483    setRootElemName(const_cast<XMLCh*>(rootDecl->getRawName()));
484
485    Janitor<DTDElementDecl> rootDeclJanitor(rootDecl);
486    rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
487    rootDecl->setExternalElemDeclaration(true);
488    if (!fUseCachedGrammar)
489    {
490        fGrammar->putElemDecl(rootDecl);
491        rootDeclJanitor.release();
492    }
493    else
494    {
495        // attach this to the undeclared element pool so that it gets deleted
496        XMLElementDecl* elemDecl = fDTDElemNonDeclPool->getByKey(bbRootName.getRawBuffer());
497        if (elemDecl)
498        {
499            rootDecl->setId(elemDecl->getId());
500        }
501        else
502        {
503            rootDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)rootDecl));
504            rootDeclJanitor.release();
505        }
506    }
507
508    // Skip any spaces after the name
509    fReaderMgr.skipPastSpaces();
510
511    //  And now if we are looking at a >, then we are done. It is not
512    //  required to have an internal or external subset, though why you
513    //  would not escapes me.
514    if (fReaderMgr.skippedChar(chCloseAngle))
515    {
516        //  If we have a doc type handler and advanced callbacks are enabled,
517        //  call the doctype event.
518        if (fDocTypeHandler)
519            fDocTypeHandler->doctypeDecl(*rootDecl, 0, 0, false);
520        return;
521    }
522
523    // either internal/external subset
524    if (fValScheme == Val_Auto && !fValidate)
525        fValidate = true;
526
527    bool    hasIntSubset = false;
528    bool    hasExtSubset = false;
529    XMLCh*  sysId = 0;
530    XMLCh*  pubId = 0;
531
532    DTDScanner dtdScanner
533    (
534        (DTDGrammar*) fGrammar
535        , fDocTypeHandler
536        , fGrammarPoolMemoryManager
537        , fMemoryManager
538    );
539
540    dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
541
542    //  If the next character is '[' then we have no external subset cause
543    //  there is no system id, just the opening character of the internal
544    //  subset. Else, has to be an id.
545    //
546    // Just look at the next char, don't eat it.
547    if (fReaderMgr.peekNextChar() == chOpenSquare)
548    {
549        hasIntSubset = true;
550    }
551    else
552    {
553        // Indicate we have an external subset
554        hasExtSubset = true;
555        fHasNoDTD = false;
556
557        // Get buffers for the ids
558        XMLBufBid bbPubId(&fBufMgr);
559        XMLBufBid bbSysId(&fBufMgr);
560
561        // Get the external subset id
562        if (!dtdScanner.scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), DTDScanner::IDType_External))
563        {
564            fReaderMgr.skipPastChar(chCloseAngle);
565            return;
566        }
567
568        // Get copies of the ids we got
569        pubId = XMLString::replicate(bbPubId.getRawBuffer(), fMemoryManager);
570        sysId = XMLString::replicate(bbSysId.getRawBuffer(), fMemoryManager);
571
572        // Skip spaces and check again for the opening of an internal subset
573        fReaderMgr.skipPastSpaces();
574
575        // Just look at the next char, don't eat it.
576        if (fReaderMgr.peekNextChar() == chOpenSquare)
577        {
578            hasIntSubset = true;
579        }
580    }
581
582    // Insure that the ids get cleaned up, if they got allocated
583    ArrayJanitor<XMLCh> janSysId(sysId, fMemoryManager);
584    ArrayJanitor<XMLCh> janPubId(pubId, fMemoryManager);
585
586    //  If we have a doc type handler and advanced callbacks are enabled,
587    //  call the doctype event.
588    if (fDocTypeHandler)
589        fDocTypeHandler->doctypeDecl(*rootDecl, pubId, sysId, hasIntSubset, hasExtSubset);
590
591    //  Ok, if we had an internal subset, we are just past the [ character
592    //  and need to parse that first.
593    if (hasIntSubset)
594    {
595        // Eat the opening square bracket
596        XMLCh openSquareBracket = fReaderMgr.getNextChar();
597        assert (openSquareBracket == chOpenSquare);
598
599        checkInternalDTD(hasExtSubset, sysId, pubId);
600
601        //  And try to scan the internal subset. If we fail, try to recover
602        //  by skipping forward tot he close angle and returning.
603        if (!dtdScanner.scanInternalSubset())
604        {
605            fReaderMgr.skipPastChar(chCloseAngle);
606            return;
607        }
608
609        fHasInternalOrExternalDTD = true;
610
611        //  Do a sanity check that some expanded PE did not propogate out of
612        //  the doctype. This could happen if it was terminated early by bad
613        //  syntax.
614        if (fReaderMgr.getReaderDepth() > 1)
615        {
616            emitError(XMLErrs::PEPropogated);
617
618            // Ask the reader manager to pop back down to the main level
619            fReaderMgr.cleanStackBackTo(1);
620        }
621
622        fReaderMgr.skipPastSpaces();       
623    }
624
625    // And that should leave us at the closing > of the DOCTYPE line
626    if (!fReaderMgr.skippedChar(chCloseAngle))
627    {
628        //  Do a special check for the common scenario of an extra ] char at
629        //  the end. This is easy to recover from.
630        if (fReaderMgr.skippedChar(chCloseSquare) && fReaderMgr.skippedChar(chCloseAngle))
631        {
632            emitError(XMLErrs::ExtraCloseSquare);
633        }
634         else
635        {
636            emitError(XMLErrs::UnterminatedDOCTYPE);
637            fReaderMgr.skipPastChar(chCloseAngle);
638        }
639    }
640
641    //  If we had an external subset, then we need to deal with that one
642    //  next. If we are reusing the validator, then don't scan it.
643    if (hasExtSubset)
644    {
645        InputSource* srcUsed=0;
646        Janitor<InputSource> janSrc(srcUsed);
647        // If we had an internal subset and we're using the cached grammar, it
648        // means that the ignoreCachedDTD is set, so we ignore the cached
649        // grammar
650        if (fUseCachedGrammar && !hasIntSubset)
651        {
652            srcUsed = resolveSystemId(sysId, pubId);
653            if (srcUsed)
654            {
655                janSrc.reset(srcUsed);
656                Grammar* grammar = fGrammarResolver->getGrammar(srcUsed->getSystemId());
657
658                if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType)
659                {
660                    fDTDGrammar = (DTDGrammar*) grammar;
661                    fGrammar = fDTDGrammar;
662                    fValidator->setGrammar(fGrammar);
663                    // If we don't report at least the external subset boundaries,
664                    // an advanced document handler cannot know when the DTD end,
665                    // since we've already sent a doctype decl that indicates there's
666                    // there's an external subset.
667                    if (fDocTypeHandler)
668                    {
669                        fDocTypeHandler->startExtSubset();
670                        fDocTypeHandler->endExtSubset();
671                    }
672
673                    return;
674                }
675            }
676        }
677
678        if (fLoadExternalDTD || fValidate)
679        {
680            // And now create a reader to read this entity
681            XMLReader* reader;
682            if (srcUsed)
683            {
684                reader = fReaderMgr.createReader
685                (
686                    *srcUsed
687                    , false
688                    , XMLReader::RefFrom_NonLiteral
689                    , XMLReader::Type_General
690                    , XMLReader::Source_External
691                    , fCalculateSrcOfs
692                    , fLowWaterMark
693                );
694            }
695            else
696            {
697                reader = fReaderMgr.createReader
698                (
699                    sysId
700                    , pubId
701                    , false
702                    , XMLReader::RefFrom_NonLiteral
703                    , XMLReader::Type_General
704                    , XMLReader::Source_External
705                    , srcUsed
706                    , fCalculateSrcOfs
707                    , fLowWaterMark
708                    , fDisableDefaultEntityResolution
709                );
710                janSrc.reset(srcUsed);
711            }
712            //  If it failed then throw an exception
713            if (!reader)
714                ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed ? srcUsed->getSystemId() : sysId, fMemoryManager);
715
716            if (fToCacheGrammar)
717            {
718                unsigned int stringId = fGrammarResolver->getStringPool()->addOrFind(srcUsed->getSystemId());
719                const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(stringId);
720
721                fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
722                ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr);
723                fGrammarResolver->putGrammar(fGrammar);
724            }
725
726            //  In order to make the processing work consistently, we have to
727            //  make this look like an external entity. So create an entity
728            //  decl and fill it in and push it with the reader, as happens
729            //  with an external entity. Put a janitor on it to insure it gets
730            //  cleaned up. The reader manager does not adopt them.
731            const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
732            DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
733            declDTD->setSystemId(sysId);
734            declDTD->setIsExternal(true);
735            Janitor<DTDEntityDecl> janDecl(declDTD);
736
737            // Mark this one as a throw at end
738            reader->setThrowAtEnd(true);
739
740            // And push it onto the stack, with its pseudo name
741            fReaderMgr.pushReader(reader, declDTD);
742
743            // Tell it its not in an include section
744            dtdScanner.scanExtSubsetDecl(false, true);
745
746            fHasInternalOrExternalDTD = true;
747        }
748    }
749}
750
751// ---------------------------------------------------------------------------
752//  IGXMLScanner: Helper methods
753// ---------------------------------------------------------------------------
754void IGXMLScanner::resizeElemState()
755{
756        unsigned int newSize = fElemStateSize * 2;
757        unsigned int* newElemState = (unsigned int*) fMemoryManager->allocate
758        (
759                newSize * sizeof(unsigned int)
760        ); //new unsigned int[newSize];
761        unsigned int* newElemLoopState = (unsigned int*) fMemoryManager->allocate
762        (
763                newSize * sizeof(unsigned int)
764        ); //new unsigned int[newSize];
765
766        // Copy the existing values
767        unsigned int index = 0;
768        for (; index < fElemStateSize; index++)
769        {
770                newElemState[index] = fElemState[index];
771                newElemLoopState[index] = fElemLoopState[index];
772        }
773
774        for (; index < newSize; index++)
775                newElemLoopState[index] = newElemState[index] = 0;
776
777        // Delete the old array and udpate our members
778        fMemoryManager->deallocate(fElemState); //delete [] fElemState;
779        fMemoryManager->deallocate(fElemLoopState); //delete [] fElemState;
780        fElemState = newElemState;
781        fElemLoopState = newElemLoopState;
782        fElemStateSize = newSize;
783}
784
785// ---------------------------------------------------------------------------
786//  IGXMLScanner: Grammar preparsing
787// ---------------------------------------------------------------------------
788Grammar* IGXMLScanner::loadGrammar(const   InputSource& src
789                                                                   , const short        grammarType
790                                                                   , const bool         toCache)
791{
792        Grammar* loadedGrammar = 0;
793
794        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
795
796        try
797        {
798                fGrammarResolver->cacheGrammarFromParse(false);
799                // if the new grammar has to be cached, better use the already cached
800                // grammars, or the an exception will be thrown when caching an already
801                // cached grammar
802                fGrammarResolver->useCachedGrammarInParse(toCache);
803                fRootGrammar = 0;
804
805                // If fValScheme is set to auto, turn validation on.
806                fValidate = fValidate | (fValScheme == Val_Auto);
807
808                // Reset some status flags
809                fInException = false;
810                fStandalone = false;
811                fErrorCount = 0;
812                fHasNoDTD = true;
813                if (grammarType == Grammar::SchemaGrammarType)
814                {
815                        loadedGrammar = loadXMLSchemaGrammar(src, toCache);
816                }
817                else if (grammarType == Grammar::DTDGrammarType)
818                {
819                        loadedGrammar = loadDTDGrammar(src, toCache);
820                }
821        }
822        //  NOTE:
823        //
824        //  In all of the error processing below, the emitError() call MUST come
825        //  before the flush of the reader mgr, or it will fail because it tries
826        //  to find out the position in the XML source of the error.
827        catch(const XMLErrs::Codes)
828        {
829                // This is a 'first fatal error' type exit, so fall through
830        }
831        catch(const XMLValid::Codes)
832        {
833                // This is a 'first fatal error' type exit, so fall through
834        }
835        catch(const XMLException& excToCatch)
836        {
837                //  Emit the error and catch any user exception thrown from here. Make
838                //  sure in all cases we flush the reader manager.
839                fInException = true;
840                try
841                {
842                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
843                                emitError
844                                (
845                                        XMLErrs::XMLException_Warning
846                                        , excToCatch.getCode()
847                                        , excToCatch.getMessage()
848                                );
849                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
850                                emitError
851                                (
852                                        XMLErrs::XMLException_Fatal
853                                        , excToCatch.getCode()
854                                        , excToCatch.getMessage()
855                                );
856                        else
857                                emitError
858                                (
859                                        XMLErrs::XMLException_Error
860                                        , excToCatch.getCode()
861                                        , excToCatch.getMessage()
862                                );
863                }
864                catch(const OutOfMemoryException&)
865                {
866                        // This is a special case for out-of-memory
867                        // conditions, because resetting the ReaderMgr
868                        // can be problematic.
869                        resetReaderMgr.release();
870
871                        throw;
872                }
873        }
874        catch(const OutOfMemoryException&)
875        {
876                // This is a special case for out-of-memory
877                // conditions, because resetting the ReaderMgr
878                // can be problematic.
879                resetReaderMgr.release();
880
881                throw;
882        }
883
884        return loadedGrammar;
885}
886
887// ---------------------------------------------------------------------------
888//  IGXMLScanner: Grammar preparsing
889// ---------------------------------------------------------------------------
890void IGXMLScanner::resetCachedGrammar ()
891{
892        fCachedSchemaInfoList->removeAll();
893}
894
895// ---------------------------------------------------------------------------
896//  IGXMLScanner: Grammar preparsing
897// ---------------------------------------------------------------------------
898Grammar* IGXMLScanner::loadDTDGrammar( const InputSource& src,
899                                                                           const bool toCache)
900{
901        // Reset the validators
902        fDTDValidator->reset();
903        if (fValidatorFromUser)
904                fValidator->reset();
905
906        if (!fValidator->handlesDTD())
907        {
908                if (fValidatorFromUser && fValidate)
909                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
910                else
911                {
912                        fValidator = fDTDValidator;
913                }
914        }
915
916        fDTDGrammar = (DTDGrammar*) fGrammarResolver->getGrammar(XMLUni::fgDTDEntityString);
917
918        if (fDTDGrammar)
919        {
920                fDTDGrammar->reset();
921        }
922        else
923        {
924                fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager);
925                fGrammarResolver->putGrammar(fDTDGrammar);
926        }
927
928        fGrammar = fDTDGrammar;
929        fGrammarType = fGrammar->getGrammarType();
930        fValidator->setGrammar(fGrammar);
931
932        //  And for all installed handlers, send reset events. This gives them
933        //  a chance to flush any cached data.
934        if (fDocHandler)
935                fDocHandler->resetDocument();
936        if (fEntityHandler)
937                fEntityHandler->resetEntities();
938        if (fErrorReporter)
939                fErrorReporter->resetErrors();
940
941        // Clear out the id reference list
942        resetValidationContext();
943        // and clear out the darned undeclared DTD element pool...
944        fDTDElemNonDeclPool->removeAll();
945
946        if (toCache)
947        {
948                unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId());
949                const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId);
950
951                fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
952                ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr);
953                fGrammarResolver->putGrammar(fGrammar);
954        }
955
956        //  Handle the creation of the XML reader object for this input source.
957        //  This will provide us with transcoding and basic lexing services.
958        XMLReader* newReader = fReaderMgr.createReader
959        (
960                src
961                , false
962                , XMLReader::RefFrom_NonLiteral
963                , XMLReader::Type_General
964                , XMLReader::Source_External
965                , fCalculateSrcOfs
966                , fLowWaterMark
967        );
968
969        if (!newReader)
970        {
971                if (src.getIssueFatalErrorIfNotFound())
972                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
973                else
974                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
975        }
976
977        //  In order to make the processing work consistently, we have to
978        //  make this look like an external entity. So create an entity
979        //  decl and fill it in and push it with the reader, as happens
980        //  with an external entity. Put a janitor on it to insure it gets
981        //  cleaned up. The reader manager does not adopt them.
982        const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
983        DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
984        declDTD->setSystemId(src.getSystemId());
985        declDTD->setIsExternal(true);
986        Janitor<DTDEntityDecl> janDecl(declDTD);
987
988        // Mark this one as a throw at end
989        newReader->setThrowAtEnd(true);
990
991        // And push it onto the stack, with its pseudo name
992        fReaderMgr.pushReader(newReader, declDTD);
993
994        //  If we have a doc type handler and advanced callbacks are enabled,
995        //  call the doctype event.
996        if (fDocTypeHandler)
997        {
998                // Create a dummy root
999                DTDElementDecl* rootDecl = new (fGrammarPoolMemoryManager) DTDElementDecl
1000                (
1001                        gDTDStr
1002                        , XMLNamespaceResolver::fEmptyUriId
1003                        , DTDElementDecl::Any
1004                        , fGrammarPoolMemoryManager
1005                );
1006                rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
1007                rootDecl->setExternalElemDeclaration(true);
1008                Janitor<DTDElementDecl> janSrc(rootDecl);
1009
1010                fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false, true);
1011        }
1012
1013        // Create DTDScanner
1014        DTDScanner dtdScanner
1015        (
1016                (DTDGrammar*) fGrammar
1017                , fDocTypeHandler
1018                , fGrammarPoolMemoryManager
1019                , fMemoryManager
1020        );
1021        dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
1022
1023        // Tell it its not in an include section
1024        dtdScanner.scanExtSubsetDecl(false, true);
1025
1026        if (fValidate)
1027        {
1028                //  validate the DTD scan so far
1029                fValidator->preContentValidation(false, true);
1030        }
1031
1032        if (toCache)
1033                fGrammarResolver->cacheGrammars();
1034
1035        return fDTDGrammar;
1036}
1037
1038// ---------------------------------------------------------------------------
1039//  IGXMLScanner: Helper methods
1040// ---------------------------------------------------------------------------
1041
1042bool IGXMLScanner::checkNamespaceAttribute(const bool isXMLNS, const XMLSymbol & attribute, const XMLCh * value, bool declared, DatatypeValidator * & attrValidator)
1043{
1044    bool validate = fValidate & declared;
1045    bool tokenize = false;
1046
1047    if (likely(isXMLNS))
1048    {
1049        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
1050        // these values ought to be validated but the authors of Xerces reported a performance degradation of ~4%?
1051        // they opted to disable validation with the intention of doing a performance assessment of the anyuri datatype.
1052        // (not sure how they arrived at this figure; it seems excessive)
1053        validate = false;
1054    }
1055    else // if (isXSI)
1056    {
1057        const gid_t localPartId = attribute.getLocalPartId();
1058
1059        switch (localPartId)
1060        {
1061            case XMLSymbolTable::Type:
1062                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME);
1063                break;
1064            case XMLSymbolTable::Nil:
1065                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN);
1066                break;
1067            case XMLSymbolTable::SchemaLocation:
1068                tokenize = true;
1069            case XMLSymbolTable::NoNamespaceSchemaLocation:
1070                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
1071                // these values ought to be validated but the authors of Xerces reported a performance degradation of ~4%?
1072                // they opted to disable validation with the intention of doing a performance assessment of the anyuri datatype.
1073                // (not sure how they arrived at this figure; it seems excessive)
1074                validate = false;
1075                break;
1076            default:
1077                return false; // bound to the xsi namespace but is not one of the predefined xsi attributes?
1078        }
1079    }
1080
1081    if (validate && attrValidator)
1082    {
1083        ValidationContext* const validationContext = getValidationContext();
1084
1085        if (validationContext)
1086        {
1087            try
1088            {
1089                if (tokenize)
1090                {
1091                    XMLStringTokenizer tokenizer(value, fMemoryManager);
1092                    while (tokenizer.hasMoreTokens())
1093                    {
1094                        attrValidator->validate(tokenizer.nextToken(), validationContext, fMemoryManager);
1095                    }
1096                }
1097                else
1098                {
1099                    attrValidator->validate(value, validationContext, fMemoryManager);
1100                }
1101            }
1102            catch (const XMLException& idve)
1103            {
1104                fValidator->emitError(XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
1105            }
1106        }
1107    }
1108
1109    return true;
1110}
1111
1112bool IGXMLScanner::tokenizeAttributeValue
1113(
1114    const XMLCh * const             value
1115    , const XMLSize_t               length
1116    , XMLBuffer &                   toFill
1117)
1118{
1119    DEBUG_GRAMMAR_MESSAGE("tokenizeAttributeValue(" << value << ',' << length << ')')
1120
1121    // TODO: this is a very poor method of handling tokenization. It assumes that the value was improperly tokenized when
1122    // in all likelyhood the document is valid.
1123
1124    toFill.reset();
1125
1126    if (likely(length > 0))
1127    {
1128        // any non-space whitespace characters within the value must have been inserted by character reference expansion.
1129        // only iterate through actual spaces.
1130        XMLChIterator<chSpace> itr(value, length);
1131        // find the very first non-whitespace character.
1132        if (itr.nextc())
1133        {
1134            for (;;)
1135            {
1136                size_t pos = itr.pos();
1137                // are there any whitespace characters after the first whitespace character?
1138                if (!itr.next())
1139                {
1140                    toFill.append(&value[pos], length - pos);
1141                    break;
1142                }
1143                toFill.append(&value[pos], itr.pos() - pos);
1144
1145                // get the position of the next non-whitespace character
1146                if (!itr.nextc())
1147                {
1148                    break;
1149                }
1150                // if there is one, then add a space between the tokens
1151                toFill.append(chSpace);
1152            }
1153        }
1154    }
1155
1156    return (toFill.getLen() != length);
1157}
1158
1159void IGXMLScanner::switchToSchemaGrammar()
1160{
1161    // If we are in the DTD mode, try to switch to the Schema mode. For that we need to find any
1162    // XML Schema grammar that we can switch to. Such a grammar can only come from the cache (if
1163    // it came from the schemaLocationattribute, we would be in the Schema mode already).
1164
1165    XMLGrammarPool* pool = fGrammarResolver->getGrammarPool ();
1166    RefHashTableOfEnumerator<Grammar> i = pool->getGrammarEnumerator ();
1167
1168    while (i.hasMoreElements ())
1169    {
1170        Grammar& gr (i.nextElement());
1171
1172        if (gr.getGrammarType () == Grammar::SchemaGrammarType)
1173        {
1174            switchGrammar (gr.getTargetNamespace ());
1175            break;
1176        }
1177    }
1178}
1179
1180void IGXMLScanner::resetPSVIElemContext()
1181{
1182        fPSVIElemContext.fIsSpecified = false;
1183        fPSVIElemContext.fErrorOccurred = false;
1184    fPSVIElemContext.fElemDepth = 0;
1185    fPSVIElemContext.fFullValidationDepth = 0;
1186    fPSVIElemContext.fNoneValidationDepth = 0;
1187        fPSVIElemContext.fCurrentDV = 0;
1188        fPSVIElemContext.fCurrentTypeInfo = 0;
1189        fPSVIElemContext.fNormalizedValue = 0;
1190}
1191
1192bool IGXMLScanner::expandEntityReference
1193(
1194    const XMLCh *                   entityReference
1195    , const XMLSize_t               /* length */
1196    , const bool                    inAttributeValue
1197    , XMLBuffer &                   toFill
1198    , XMLReplacementText &          replacementText
1199)
1200{
1201    // here's where we need to check if there's a SecurityManager,
1202        // how many entity references we've had
1203    if (fSecurityManager && ++fEntityExpansionCount > fEntityExpansionLimit)
1204        {
1205                XMLCh expLimStr[32];
1206                XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
1207                emitError
1208                (
1209                        XMLErrs::EntityExpansionLimitExceeded
1210                        , expLimStr
1211                );
1212                // there seems nothing  better to be done than to reset the entity expansion counter
1213                fEntityExpansionCount = 0;
1214        }
1215
1216        // Look up the name in the general entity pool
1217    XMLEntityDecl * decl = fDTDGrammar->getEntityDecl(entityReference);
1218        InputSource * srcUsed;
1219
1220        // If it does not exist, then obviously an error
1221        if (unlikely(!decl))
1222        {
1223                // XML 1.0 Section 4.1
1224                // Well-formedness Constraint for entity not found:
1225        //   In a document without any DTD, a document with only an internal DTD subset that contains no parameter entity references,
1226                //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
1227                //      or a parameter entity
1228                //
1229                // Else it's Validity Constraint
1230                if (fStandalone || fHasNoDTD)
1231                {
1232            emitError(XMLErrs::EntityNotFound, entityReference);
1233                }
1234                else if (fValidate)
1235                {
1236            fValidator->emitError(XMLValid::VC_EntityNotFound, entityReference);
1237                }
1238                return 0;
1239        }
1240
1241        // XML 1.0 Section 4.1
1242        //  If we are a standalone document, then it has to have been declared
1243        //  in the internal subset.
1244        if (unlikely(fStandalone && !decl->getDeclaredInIntSubset()))
1245        {
1246        emitError(XMLErrs::IllegalRefInStandalone, entityReference);
1247        }
1248
1249        XMLReader * reader;
1250        if (unlikely(decl->isExternal()))
1251        {
1252        if (unlikely(inAttributeValue))
1253        {
1254            emitError(XMLErrs::NoExtRefsInAttValue);
1255            return 0;
1256        }
1257
1258                // If its unparsed, then its not valid here
1259                if (unlikely(decl->isUnparsed()))
1260                {
1261            emitError(XMLErrs::NoUnparsedEntityRefs, entityReference);
1262                        return 0;
1263                }
1264
1265                // And now create a reader to read this entity
1266                reader = fReaderMgr.createReader
1267                (
1268                        decl->getBaseURI()
1269                        , decl->getSystemId()
1270                        , decl->getPublicId()
1271                        , false
1272                        , XMLReader::RefFrom_NonLiteral
1273                        , XMLReader::Type_General
1274                        , XMLReader::Source_External
1275                        , srcUsed
1276                        , fCalculateSrcOfs
1277                        , fLowWaterMark
1278                        , fDisableDefaultEntityResolution
1279                );
1280
1281                // Put a janitor on the source so it gets cleaned up on exit
1282                Janitor<InputSource> janSrc(srcUsed);
1283
1284                //  If the creation failed, and its not because the source was empty,
1285                //  then emit an error and return.
1286                if (!reader)
1287                {
1288                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed ? srcUsed->getSystemId() : decl->getSystemId(), fMemoryManager);
1289                }
1290
1291        fReaderMgr.pushReader(reader, decl);
1292
1293        // If it starts with the XML string, then parse a text decl
1294        if (checkXMLDecl(true))
1295        {
1296            scanXMLDecl(Decl_Text);
1297        }
1298
1299        reader = fReaderMgr.getCurrentReader();
1300        // get the line, column and version information from the Reader; one of these will likely
1301        // differ from the source document.
1302        replacementText.fLine = reader->getLineNumber();
1303        replacementText.fColumn = reader->getColumnNumber();
1304        replacementText.fSystemId = decl->getSystemId();
1305        replacementText.fPublicId = decl->getPublicId();
1306        replacementText.fType = XMLReplacementText::GeneralEntity;
1307        // now obtain the entire the value
1308        reader->fill(toFill);
1309        // and pop the entity reader off the stack
1310        fReaderMgr.popReader();
1311        }
1312        else // internal entity
1313        {
1314                //  If its a predefined entity reference...
1315                if (decl->getIsSpecialChar())
1316                {
1317            toFill.set(decl->getValue()[0]);
1318            replacementText.fType = XMLReplacementText::PredefinedEntity;
1319                }
1320        else
1321        {
1322            reader = fReaderMgr.getCurrentReader();
1323
1324            toFill.set(decl->getValue(), decl->getValueLen());
1325            replacementText.fLine = decl->getBaseLine();
1326            replacementText.fColumn = decl->getBaseColumn();
1327            replacementText.fSystemId = reader->getSystemId();
1328            replacementText.fPublicId = reader->getPublicId();
1329            replacementText.fType = XMLReplacementText::GeneralEntity;
1330        }
1331        }
1332        return 1;
1333}
1334
1335void IGXMLScanner::reportRequiredAttribute(const DTDAttDef & attDef)
1336{
1337    XMLBufBid bbAttName(&fBufMgr);
1338    XMLBuffer & bAttName = bbAttName.getBuffer();
1339    const XMLCh * fullName = attDef.getFullName();
1340    if (fDoNamespaces)
1341    {
1342        int colonInd = -1;
1343        const XMLCh * uri = getURIForQName(fullName, colonInd);
1344        if (uri)
1345        {
1346            bAttName.set(chOpenCurly);
1347            bAttName.append(uri);
1348            bAttName.append(chCloseCurly);
1349            bAttName.append(&fullName[colonInd + 1]);
1350            fullName = bAttName.getRawBuffer();
1351        }
1352    }
1353    fDTDValidator->emitError(XMLValid::RequiredAttrNotProvided, fullName);
1354}
1355
1356void IGXMLScanner::reportRequiredAttribute(const SchemaAttDef & attDef)
1357{
1358    XMLBufBid bbAttName(&fBufMgr);
1359    XMLBuffer & bAttName = bbAttName.getBuffer();
1360    const XMLCh * fullName = attDef.getFullName();
1361    if (fDoNamespaces)
1362    {
1363        int colonInd = -1;
1364        const XMLCh * uri = getURIForQName(fullName, colonInd);
1365        if (uri)
1366        {
1367            bAttName.set(chOpenCurly);
1368            bAttName.append(uri);
1369            bAttName.append(chCloseCurly);
1370            bAttName.append(&fullName[colonInd + 1]);
1371            fullName = bAttName.getRawBuffer();
1372        }
1373    }
1374    fSchemaValidator->emitError(XMLValid::RequiredAttrNotProvided, fullName);
1375}
1376
1377
1378void IGXMLScanner::reportAttributeNotDefinedForElement(const DTDElementDecl & elemDecl, const XMLCh * attributeName)
1379{
1380    XMLBufBid bbAttName(&fBufMgr);
1381    XMLBuffer & bAttName = bbAttName.getBuffer();
1382    const XMLCh * fullName = elemDecl.getFullName();
1383    if (fDoNamespaces)
1384    {
1385        int colonInd = -1;
1386        const XMLCh * uri = getURIForQName(attributeName, colonInd);
1387        if (uri)
1388        {
1389            bAttName.set(chOpenCurly);
1390            bAttName.append(uri);
1391            bAttName.append(chCloseCurly);
1392            bAttName.append(&attributeName[colonInd + 1]);
1393            attributeName = bAttName.getRawBuffer();
1394        }
1395    }
1396    fDTDValidator->emitError(XMLValid::AttNotDefinedForElement, attributeName, fullName);
1397}
1398
1399void IGXMLScanner::endElementPSVI(SchemaElementDecl* const, DatatypeValidator * const)
1400{
1401    DEPRECATED_FEATURE_IN_ICXML
1402}
1403
1404XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.