source: icXML/icXML-devel/src/icxmlc/parsers/XMLNamespaceParser.hpp @ 3157

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

Fixes for icXML 0.9

File size: 26.8 KB
Line 
1#ifndef XMLNAMESPACEPARSER_HPP
2#define XMLNAMESPACEPARSER_HPP
3
4#include <icxmlc/XMLParser.hpp>
5#include <icxmlc/parsers/XMLSchemaLoader.hpp>
6#include <icxmlc/XMLReplacementText.hpp>
7#include <icxmlc/XMLConfig.hpp>
8
9XERCES_CPP_NAMESPACE_BEGIN
10
11template<class ScannerType>
12class XMLNamespaceParser
13{
14    typedef DynamicArray<gid_t, INITIAL_ATTRIBUTE_LIST_SIZE> GidArrayType;
15
16    typedef DynamicArray<bool, INITIAL_ATTRIBUTE_LIST_SIZE> BoolArrayType;
17
18public:
19
20    inline XMLNamespaceParser
21    (
22        XMLParser &                           parser
23        , XMLNamespaceResolver &              namespaceResolver       
24        , const XMLSymbolTable &              symbolTable
25        , const XMLReferenceTable &           referenceTable
26        , XMLSchemaLoader<ScannerType> &      schemaLoader
27        , ScannerType &                       scanner
28    )         
29    : fContentStream(&parser.fContentStream[0])
30    , fCursorPtr(&parser.fContentStream[parser.fContentIdx])
31    , fCursorEndPtr(parser.fCursorEndPtr)
32    , fSymbolStream(&parser.fSymbolStream[0])
33    , fSymbolPtr(&fSymbolStream[0])
34    , fSymbolCount(parser.fSymbolCount)
35    , fReferenceStream(&parser.fReferenceStream[0])
36    , fReferencePtr(fReferenceStream)
37    , fReferenceCount(parser.fReferenceCount)
38    , fStringEndStream(&parser.fStringEndStream[0])
39    , fStringEndPtr(parser.fStringEndPtr)
40    , fStringCount(parser.fStringCount)
41    , fUriStream(parser.fUriStream)
42    , fUriPtr(&parser.fUriStream[0])
43    , fUriCount(parser.fUriCount)
44    , fContextStream(parser.fContextStream)
45    , fContextPtr(&parser.fContextStream[0])
46    , fInMarkup(parser.fInMarkup)
47    , fEndsWithPartialContent(parser.fEndsWithPartialContent)
48    , fIsXMLV1_1(scanner.getXMLVersion() == XMLReader::XMLV1_1)
49    , fMarkupCount(parser.fMarkupCount)
50    , fMaxAttributeCount(parser.fMaxAttributeCount)
51    , fMaxScope(parser.fMaxScope)
52    , fLocalPartIds(fMaxAttributeCount)
53    , fNamespaceResolver(namespaceResolver)
54    , fReferenceTable(referenceTable)
55    , fSymbolTable(symbolTable)
56    , fSchemaLoader(schemaLoader)
57    , fContainsXsiTypeOrNil(parser.fContainsXsiTypeOrNil)
58    , fScanner(scanner)
59    , fEntityContentBuffer(parser.fEntityContentBuffer)
60    {
61        DEBUG_NAMESPACE_MESSAGE("######################################################################");
62        DEBUG_NAMESPACE_MESSAGE("BEGIN NAMESPACE PROCESSING: fMarkupCount=" << fMarkupCount << " fUriCount=" << fUriCount << " fMaxScope=" << fMaxScope);
63        DEBUG_NAMESPACE_MESSAGE("######################################################################");
64
65        fContainsXsiTypeOrNil = false;
66
67        DEBUG_MESSAGE("XMLNamespaceParser::fStringCount=" << fStringCount)
68    }
69
70    inline XMLNamespaceParser
71    (
72        XMLNamespaceParser &                parser
73        , const XMLReplacementText &        entity
74    )
75    : fContentStream(entity.fContentStream)
76    , fCursorPtr(&entity.fContentStream[0])
77    , fCursorEndPtr(&entity.fContentStream[entity.fContentLength])
78    , fSymbolStream(entity.fSymbolStream)
79    , fSymbolPtr(&entity.fSymbolStream[0])
80    , fSymbolCount(entity.fSymbolCount)
81    , fReferenceStream(entity.fReferenceStream)
82    , fReferencePtr(fReferenceStream)
83    , fReferenceCount(entity.fReferenceCount)
84    , fStringEndStream(entity.fStringEndStream)
85    , fStringEndPtr(&fStringEndStream[0])
86    , fStringCount(entity.fStringEndCount)
87    , fUriStream(parser.fUriStream)
88    , fUriPtr(parser.fUriPtr)
89    , fUriCount(parser.fUriCount)
90    , fContextStream(parser.fContextStream)
91    , fContextPtr(parser.fContextPtr)
92    , fInMarkup(false)
93    , fEndsWithPartialContent(false)
94    , fIsXMLV1_1(parser.fIsXMLV1_1) // should be in the entity!
95    , fMarkupCount(entity.fMarkupCount)
96    , fMaxAttributeCount(parser.fMaxAttributeCount)
97    , fMaxScope(parser.fMaxScope)
98    , fLocalPartIds(fMaxAttributeCount)
99    , fNamespaceResolver(parser.fNamespaceResolver)
100    , fReferenceTable(parser.fReferenceTable)
101    , fSymbolTable(parser.fSymbolTable)
102    , fSchemaLoader(parser.fSchemaLoader)
103    , fContainsXsiTypeOrNil(parser.fContainsXsiTypeOrNil)
104    , fScanner(parser.fScanner)
105    , fEntityContentBuffer(parser.fEntityContentBuffer)
106    {
107        DEBUG_NAMESPACE_MESSAGE("######################################################################");
108        DEBUG_NAMESPACE_MESSAGE("BEGIN ENTITY NAMESPACE PROCESSING: " << fMarkupCount);
109        DEBUG_NAMESPACE_MESSAGE("######################################################################");
110    }
111
112    inline ~XMLNamespaceParser()
113    {
114        DEBUG_NAMESPACE_MESSAGE("######################################################################");
115        DEBUG_NAMESPACE_MESSAGE("END NAMESPACE PROCESSING: fContextIdCount=" << (fContextPtr - &fContextStream[0]));
116        DEBUG_NAMESPACE_MESSAGE("######################################################################");
117    }
118
119    void resolveNamespaces();
120
121private:
122
123    IDISA_ALWAYS_INLINE
124    void verifyUniqueNamespacedAttributeConstraint(SymbolPtrType elementPtr, UriPtrType uriStream, const gid_t * localPartIds, const size_t attCount);
125
126    void reportUnknownPrefix(SymbolPtrType from, SymbolPtrType to);
127
128    void reportDuplicateNamespacedAttribute(SymbolPtrType elementPtr, const gid_t localPartId);
129
130    /**
131     *  Recursively resolve the namespaces of the entity
132     **/
133    void resolveEntityNamespaces(const gid_t refId);
134
135    /**
136     *  Expand any entities within an attribute value
137     **/
138    size_t expandEntitiesWithinAttributeValue(ContentPtrType & value, ContentPtrType & delimiter);
139
140    IDISA_ALWAYS_INLINE
141    void skipPastAnyEntities(ContentPtrType & delimiter);
142
143    IDISA_ALWAYS_INLINE
144    const XMLSymbol & getSymbolByPtr(SymbolPtrType symbolPtr) const;
145
146    IDISA_ALWAYS_INLINE
147    gid_t resolveAttributeUriId(const size_t index, SymbolPtrType symbolPtr, bool & isXsi, bool & namespaceContextChange, bool & speculatedCorrectly, bool & unknownPrefix);
148
149    IDISA_ALWAYS_INLINE
150    gid_t resolveEndTagUriId(SymbolPtrType symbolPtr);
151
152    IDISA_ALWAYS_INLINE
153    void writeCurrentContextId(const gid_t contextId);
154
155    void checkForXsiSchemaLocationOrNoNamespaceSchemaLocation(ContentPtrType contentStream, DelimiterPtrType delimiterStream, UriPtrType uriStream, const gid_t * localPartIds, const size_t attCount);
156
157private:
158
159    const ContentPtrType                fContentStream;
160    ContentPtrType                      fCursorPtr;
161    ContentPtrType                      fCursorEndPtr;
162
163    const SymbolPtrType                 fSymbolStream;
164    SymbolPtrType                       fSymbolPtr;
165    const size_t                        fSymbolCount;
166
167    const ReferencePtrType              fReferenceStream;
168    ReferencePtrType                    fReferencePtr;
169    const size_t                        fReferenceCount;
170
171    const DelimiterPtrType              fStringEndStream;
172    DelimiterPtrType                    fStringEndPtr;
173    const size_t &                      fStringCount;
174
175    SymbolUriArray &                                    fUriStream;
176    WritableUriPtrType                  fUriPtr;
177    const size_t                        fUriCount;
178
179    SymbolUriArray &                                    fContextStream;
180    WritableUriPtrType                  fContextPtr;
181
182    const bool                          fInMarkup;
183    const bool                          fEndsWithPartialContent;
184    const bool                          fIsXMLV1_1;
185
186    size_t                              fMarkupCount;
187    bool &                              fContainsXsiTypeOrNil;
188    const size_t                        fMaxAttributeCount;
189    const size_t                        fMaxScope;
190
191    GidArrayType                        fLocalPartIds;
192
193    XMLNamespaceResolver &              fNamespaceResolver;
194    const XMLReferenceTable &           fReferenceTable;
195    const XMLSymbolTable &              fSymbolTable;
196    XMLSchemaLoader<ScannerType> &      fSchemaLoader;
197    ScannerType &                       fScanner;
198
199    XMLBuffer * const                   fEntityContentBuffer;
200};
201
202/// --------------------------------------------------------------------------------------------------------------------------------
203
204template<class ScannerType>
205void XMLNamespaceParser<ScannerType>::resolveNamespaces()
206{
207    // this needs to record any xsi:schemaLocation | xsi:noNamespaceSchemaLocation values for the parent namespace pass to process.
208    // if there is no markup remaining, stop scanning!
209    if (unlikely(fMarkupCount == 0))
210    {
211        return;
212    }
213
214    XMLCh markupChar;   
215    switch (fInMarkup)
216    {
217        for(;;)
218        {
219    case 0: DEBUG_NAMESPACE_MESSAGE("==================================================================");               
220            DEBUG_NAMESPACE_MESSAGE(" -- atContent=" << fCursorPtr << " fMarkupCount=" << fMarkupCount << " fEndsWithPartialContent=" << fEndsWithPartialContent);
221            if (unlikely(fMarkupCount == 0 && fEndsWithPartialContent))
222            {
223                break;
224            }
225            if (1)
226            {
227                const ContentPtrType cursorPtr = fCursorPtr;
228                fCursorPtr = *fStringEndPtr++;
229                assert (cursorPtr <= fCursorPtr);
230                assert (fCursorPtr <= fCursorEndPtr);
231
232                // if we found a reference, it's a general entity. check whether it contains markup and if not, skip it.
233                // make this another template parameter? not sure if it would be useful.
234                while (unlikely(*fCursorPtr == Entity))
235                {
236                    // parse the entity and record the namespaces
237                    resolveEntityNamespaces(*fReferencePtr++);
238                    // skip to the next delimiter
239                    fCursorPtr = *fStringEndPtr++;
240                }
241                ++fCursorPtr;
242            }
243    case 1: if (unlikely(fMarkupCount == 0))
244            {
245                break;
246            }
247            // advance past the trailing null char and process the next markup element
248            markupChar = *fCursorPtr;
249            {
250                bool hasAttributes = 0;
251                switch (markupChar & MarkupMask)
252                {
253                    /// ------------------------------------------------------------------------ ///
254                    case StartTagWithAttributes:
255                        hasAttributes = 1;
256                    case StartTagWithoutAttributes:
257                    {
258                        // a new namespaces is possible here! speculate that any unknown ones are acceptable, but
259                        // verify after the fact if any new ones occured.
260                        fNamespaceResolver.enterScope();
261                        const SymbolPtrType elementSymbolPtr = fSymbolPtr;
262                        const WritableUriPtrType elementUriPtr = fUriPtr;
263                        bool unknownPrefix = 0;
264                        bool namespaceContextChange = 0;
265
266                        if (hasAttributes)
267                        {
268                            const ContentPtrType initialCursorPtr = fCursorPtr;
269                            const DelimiterPtrType initialStringEndPtr = fStringEndPtr;
270
271                            for (;;)
272                            {
273                                bool observedXsi = 0;
274                                bool speculatedCorrectly = 1;
275                                size_t attCount = 0;
276
277                                do
278                                {
279                                    /// --------------------------------------------------------------------------------------------------------------
280                                    /// DOCUMENT ATTRIBUTE RESOLUTION
281                                    /// --------------------------------------------------------------------------------------------------------------
282
283                                    // extract the next attribute ...
284
285                                    *++fUriPtr = resolveAttributeUriId(attCount++, ++fSymbolPtr, observedXsi, namespaceContextChange, speculatedCorrectly, unknownPrefix);
286
287                                    // if the next markup char's value is 0 (8), then we're at the end of the start/empty tag
288                                    markupChar = *++fCursorPtr;
289                                }
290                                while ((markupChar & MarkupMask) == Attribute);
291
292                                /// --------------------------------------------------------------------------------------------------------------
293                                /// Default attribute resolution was performed in well-formedness checker
294                                /// --------------------------------------------------------------------------------------------------------------
295
296                                if (likely(speculatedCorrectly))
297                                {
298                                    verifyUniqueNamespacedAttributeConstraint(elementSymbolPtr, elementUriPtr + 1, &fLocalPartIds[0], attCount);
299
300                                    if (unlikely(observedXsi))
301                                    {
302                                        checkForXsiSchemaLocationOrNoNamespaceSchemaLocation(initialCursorPtr, initialStringEndPtr, elementUriPtr + 1, &fLocalPartIds[0], attCount);
303                                    }
304
305                                    // if we speculated correctly, then any 'unknown' prefix was found to be what we predicted it would be.
306                                    unknownPrefix &= !namespaceContextChange;
307
308                                    break;
309                                }
310                                else // note: this code can only be entered once. it is impossible to misspeculate a second time.
311                                {
312                                    DEBUG_NAMESPACE_MESSAGE("------------------------------------------------------------------");
313                                    DEBUG_NAMESPACE_MESSAGE(" *** uri speculation failed! retrying!");
314                                    DEBUG_NAMESPACE_MESSAGE("==================================================================");
315
316                                    fNamespaceResolver.misspeculated();
317                                    fCursorPtr = initialCursorPtr;
318                                    fSymbolPtr = elementSymbolPtr;
319                                    fUriPtr = elementUriPtr;
320                                    fStringEndPtr = initialStringEndPtr;
321                                    unknownPrefix = 0;
322                                }
323                            }
324
325                        }
326
327                        const XMLSymbol & element = getSymbolByPtr(elementSymbolPtr);
328                        if (unlikely(element.isXMLNS()))
329                        {
330                            fScanner.emitError(XMLErrs::NoXMLNSAsElementPrefix, element.getName());
331                        }
332
333                        // resolve the uri of the element and test whether there are any unknown prefiexes
334
335                        *elementUriPtr = fNamespaceResolver.resolveUriId(element, false, unknownPrefix);
336
337                        const bool isEmpty = (markupChar >> 3);
338
339                        ++fCursorPtr;
340                        ++fSymbolPtr;
341                        ++fUriPtr;
342                        *fContextPtr++ = fNamespaceResolver.finalizeScope(namespaceContextChange);
343
344                        DEBUG_NAMESPACE_MESSAGE
345                        (
346                            (isEmpty ? " --- atEmptyTag: " : " --- atStartTag: ") << element
347                            << " scope=" << fNamespaceResolver.getScope()
348                            << " uriId=" << *elementUriPtr
349                            << " unknownPrefix=" << unknownPrefix
350                            << " namespaceContextChange=" << namespaceContextChange
351                            << " markupCount=" << fMarkupCount
352                        );
353
354                        if (unlikely(unknownPrefix))
355                        {
356                            reportUnknownPrefix(elementSymbolPtr, fSymbolPtr);
357                        }
358
359                        // outdent scope by one if and only if this element is an empty tag
360                        if (isEmpty)
361                        {
362                            fNamespaceResolver.leaveScope(namespaceContextChange);
363                        }
364                        break;
365                    }
366                    /// ------------------------------------------------------------------------ ///
367                    case EndTag:
368                    {
369                        *fUriPtr = resolveEndTagUriId(fSymbolPtr);
370
371                        DEBUG_NAMESPACE_MESSAGE
372                        (
373                            " --- atEndTag: " << getSymbolByPtr(fSymbolPtr)
374                            << " scope=" << fNamespaceResolver.getScope()
375                            << " uriId=" << *fUriPtr
376                            << " markupCount=" << fMarkupCount
377                        );
378
379                        fCursorPtr++;
380                        fUriPtr++;
381                        fSymbolPtr++;
382                        bool namespaceContextChange;
383                        *fContextPtr++ = fNamespaceResolver.leaveScope(namespaceContextChange);
384                        break;
385                    }
386                    /// ------------------------------------------------------------------------ ///
387                    case ProcessingInstruction:
388                        fStringEndPtr++; // skip the target name
389                    case Comment:
390                    case CDATA:
391                        fStringEndPtr++; // skip the value
392                        break;
393                    default:
394                        UNREACHABLE
395                /// ------------------------------------------------------------------------ ///
396                }
397            }
398            --fMarkupCount;
399        }       
400    }
401}
402
403/// --------------------------------------------------------------------------------------------------------------------------------
404
405template<class ScannerType>
406const XMLSymbol & XMLNamespaceParser<ScannerType>::getSymbolByPtr(SymbolPtrType symbolPtr) const
407{
408    return fSymbolTable[*symbolPtr];
409}
410
411/// --------------------------------------------------------------------------------------------------------------------------------
412
413template<class ScannerType>
414gid_t XMLNamespaceParser<ScannerType>::
415resolveAttributeUriId(const size_t index, SymbolPtrType symbolPtr, bool & observedXsi, bool & namespaceContextChange, bool & speculatedCorrectly, bool & unknownPrefix)
416{
417    const XMLSymbol & attribute = getSymbolByPtr(symbolPtr);
418
419    // advance past the '=' and determine the length of the attribute value from the delimiter ptr
420    ContentPtrType value = ++fCursorPtr;
421    ContentPtrType delimiter = *fStringEndPtr++;
422
423    gid_t uriId;
424    // is this an "xmlns" attribute? if so, then we want to update the namespace table.
425    if (unlikely(attribute.isXMLNS()))
426    {
427        size_t length;
428        bool expanded = false;
429        // expand any entities within the URI string.
430        if (unlikely(*delimiter == Entity))
431        {
432            length = expandEntitiesWithinAttributeValue(value, delimiter);
433            expanded = true;
434        }
435        else
436        {
437            length = delimiter - value;
438        }
439
440        XMLErrs::Codes bindingError = XMLErrs::NoError;
441        uriId = fNamespaceResolver.bindNamespace(attribute, value, length, fIsXMLV1_1, speculatedCorrectly, namespaceContextChange, bindingError);
442        if (unlikely(bindingError != XMLErrs::NoError))
443        {
444            fScanner.emitError(bindingError, attribute.getQName()->getRawName());
445        }
446
447        WritableContentPtrType attributeMarker = const_cast<WritableContentPtrType>(fCursorPtr - 1);
448        *attributeMarker = (*attributeMarker & DefaultAttribute) | NamespaceAttribute;
449
450        if (unlikely(expanded))
451        {
452            fEntityContentBuffer->reset();
453        }
454
455        DEBUG_NAMESPACE_MESSAGE(" --- atAttribute" << (index + 1) << ' ' << getSymbolByPtr(fSymbolPtr) << '=' << value << " uriId=" << uriId << " speculatedCorrectly=" << speculatedCorrectly);
456    }
457    else // just resolve the uri gid
458    {
459        uriId = fNamespaceResolver.resolveUriId(attribute, true, unknownPrefix);
460        DEBUG_NAMESPACE_MESSAGE(" --- atAttribute" << (index + 1) << ' ' << getSymbolByPtr(fSymbolPtr) << '=' << value << " uriId=" << uriId << " observedXsi=" << observedXsi << " unknownPrefix=" << unknownPrefix);
461        observedXsi |= (uriId == XMLNamespaceResolver::fSchemaInstanceUriId);
462        // skip past any entity; we don't care about the actual value unless it's an URI.
463        skipPastAnyEntities(delimiter);
464    }
465
466    // record the localPartId for this attribute and its value
467    fLocalPartIds[index] = attribute.getLocalPartId();
468
469    fCursorPtr = delimiter;
470
471    return uriId;
472}
473
474/// --------------------------------------------------------------------------------------------------------------------------------
475
476template<class ScannerType>
477size_t XMLNamespaceParser<ScannerType>::
478expandEntitiesWithinAttributeValue(ContentPtrType & value, ContentPtrType & delimiter)
479{
480    fEntityContentBuffer->set(value, delimiter - value);
481    do
482    {
483        const XMLReplacementText & entity = fReferenceTable[*fReferencePtr++];
484        fEntityContentBuffer->append(entity.fContentStream, entity.fContentLength);
485        value = delimiter + 1;
486        delimiter = *fStringEndPtr++;
487        assert (value <= delimiter);
488        // append either the posterior content of this attribute value or any content between two entities
489        fEntityContentBuffer->append(value, delimiter - value);
490    }
491    while (*delimiter == Entity);
492    value = fEntityContentBuffer->getRawBuffer();
493    return fEntityContentBuffer->getLen();
494}
495
496/// --------------------------------------------------------------------------------------------------------------------------------
497
498template<class ScannerType>
499void XMLNamespaceParser<ScannerType>::
500skipPastAnyEntities(ContentPtrType & delimiter)
501{
502    while (unlikely(*delimiter == Entity))
503    {
504        assert (delimiter < *fStringEndPtr);
505        delimiter = *fStringEndPtr++;
506        assert (&fContentStream[0] < delimiter);
507        // skip this reference
508        fReferencePtr++;
509    }
510}
511
512/// --------------------------------------------------------------------------------------------------------------------------------
513
514template<class ScannerType>
515gid_t XMLNamespaceParser<ScannerType>::
516resolveEndTagUriId(SymbolPtrType symbolPtr)
517{
518    bool unknownPrefix;
519    return fNamespaceResolver.resolveUriId(getSymbolByPtr(symbolPtr), false, unknownPrefix);
520}
521
522/// --------------------------------------------------------------------------------------------------------------------------------
523/// ENTITY HANDLING FUNCTIONS
524/// --------------------------------------------------------------------------------------------------------------------------------
525
526template<class ScannerType>
527void XMLNamespaceParser<ScannerType>::
528resolveEntityNamespaces(const gid_t refId)
529{
530    const XMLReplacementText & entity = fReferenceTable[refId];
531    if (unlikely(entity.getMarkupCount() != 0))
532    {
533        XMLNamespaceParser<ScannerType> parser(*this, entity);
534        parser.resolveNamespaces();
535        // update the internal indexes based on what the parser resolved.
536        fUriPtr = parser.fUriPtr;
537        fContextPtr = parser.fContextPtr;
538
539        DEBUG_NAMESPACE_MESSAGE("######################################################################");
540        DEBUG_NAMESPACE_MESSAGE("END ENTITY NAMESPACE PROCESSING: " << fMarkupCount);
541        DEBUG_NAMESPACE_MESSAGE("######################################################################");
542    }
543}
544
545
546/// --------------------------------------------------------------------------------------------------------------------------------
547/// ERROR HANDLING FUNCTIONS
548/// --------------------------------------------------------------------------------------------------------------------------------
549
550template<class ScannerType>
551void XMLNamespaceParser<ScannerType>::
552reportUnknownPrefix(SymbolPtrType from, SymbolPtrType to)
553{
554    for (; from <= to; from++)
555    {
556        const XMLSymbol & symbol = getSymbolByPtr(from);
557        DEBUG_MESSAGE("symbol=" << symbol)
558
559        if (!fNamespaceResolver.isPrefixVisible(symbol.getPrefixId()))
560        {
561            fScanner.emitError(XMLErrs::UnknownPrefix, symbol.getQName()->getPrefix());
562        }
563    }
564}
565
566/*
567    Namespaces in XML 1.0 (Third Edition)
568
569        6.3 Uniqueness of Attributes
570
571        Namespace constraint: Attributes Unique
572        In XML documents conforming to this specification, no tag may contain two attributes which:
573            have identical names, or
574            have qualified names with the same local part and with prefixes which have been bound to namespace
575            names that are identical.
576*/
577
578template<class ScannerType>
579void XMLNamespaceParser<ScannerType>::
580verifyUniqueNamespacedAttributeConstraint(SymbolPtrType elementPtr, UriPtrType uriStream, const gid_t * localPartIds, const size_t attCount)
581{
582    // find a better way to do this; there must be some O(N) method in which the constant factor is < 3.
583    // if not would it be better to
584
585    for (size_t i = 1; i < attCount; i++)
586    {
587        const gid_t localPartId = localPartIds[i];
588
589        for (size_t j = 0; j < i; j++)
590        {
591            if (unlikely(localPartIds[j] == localPartId))
592            {
593                if (unlikely(uriStream[j] == uriStream[i]))
594                {
595                    reportDuplicateNamespacedAttribute(elementPtr, localPartId);
596                }
597            }
598        }
599    }
600}
601
602template<class ScannerType>
603void XMLNamespaceParser<ScannerType>::
604checkForXsiSchemaLocationOrNoNamespaceSchemaLocation(ContentPtrType contentStream, DelimiterPtrType delimiterStream, UriPtrType uriStream, const gid_t * localPartIds, const size_t attCount)
605{
606    // is this an "xsi:schemaLocation" or "xsi:noNamespaceSchemaLocation" attribute? if so, then
607    // record it as something to load later.
608
609    for (size_t i = 0; i < attCount; i++)
610    {
611        // advance past the '=' and determine the length of the attribute value from the delimiter ptr
612        const size_t length = *delimiterStream - ++contentStream;
613
614        if (uriStream[i] == XMLNamespaceResolver::fSchemaInstanceUriId)
615        {
616            bool noNamespace = 1;
617            switch (localPartIds[i])
618            {
619                case XMLSymbolTable::Type:
620                case XMLSymbolTable::Nil:
621                    fContainsXsiTypeOrNil = true;
622                    break;
623                case XMLSymbolTable::SchemaLocation:
624                    noNamespace = 0;
625                case XMLSymbolTable::NoNamespaceSchemaLocation:
626                    fSchemaLoader.addSchema(contentStream, length, noNamespace);
627            }
628        }
629        contentStream = *delimiterStream++ + 1;
630    }
631}
632
633template<class ScannerType>
634void XMLNamespaceParser<ScannerType>::
635reportDuplicateNamespacedAttribute(SymbolPtrType elementPtr, const gid_t localPartId)
636{
637    fScanner.emitError(XMLErrs::AttrAlreadyUsedInSTag, fSymbolTable.getNCName(localPartId), getSymbolByPtr(elementPtr).getName());
638}
639
640XERCES_CPP_NAMESPACE_END
641
642#endif // XMLNAMESPACEPARSER_HPP
Note: See TracBrowser for help on using the repository browser.