Newer
Older
* Copyright (c) 2002, 2003 The Apache Software Foundation. All rights
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Id$
*/
// ---------------------------------------------------------------------------
// This file holds some of the grunt work methods of IGXMLScanner.cpp to keep
// it a little more readable.
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/internal/IGXMLScanner.hpp>
#include <xercesc/internal/EndOfEntityException.hpp>
#include <xercesc/util/UnexpectedEOFException.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/framework/URLInputSource.hpp>
#include <xercesc/framework/XMLDocumentHandler.hpp>
#include <xercesc/framework/XMLEntityHandler.hpp>
#include <xercesc/framework/XMLPScanToken.hpp>
#include <xercesc/framework/XMLRefInfo.hpp>
#include <xercesc/framework/XMLGrammarPool.hpp>
#include <xercesc/framework/XMLDTDDescription.hpp>
#include <xercesc/framework/XMLSchemaDescription.hpp>
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
#include <xercesc/validators/DTD/DTDGrammar.hpp>
#include <xercesc/validators/DTD/DTDValidator.hpp>
#include <xercesc/validators/datatype/DatatypeValidator.hpp>
#include <xercesc/validators/schema/SchemaGrammar.hpp>
#include <xercesc/validators/schema/SchemaValidator.hpp>
#include <xercesc/validators/schema/TraverseSchema.hpp>
#include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
#include <xercesc/validators/schema/identity/XPathMatcherStack.hpp>
#include <xercesc/validators/schema/XSDDOMParser.hpp>
#include <xercesc/validators/schema/identity/ValueStoreCache.hpp>
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// IGXMLScanner: Private helper methods
// ---------------------------------------------------------------------------
// This method is called from scanStartTagNS() to build up the list of
// XMLAttr objects that will be passed out in the start tag callout. We
// get the key/value pairs from the raw scan of explicitly provided attrs,
// which have not been normalized. And we get the element declaration from
// which we will get any defaulted or fixed attribute defs and add those
// in as well.
unsigned int
IGXMLScanner::buildAttList(const RefVectorOf<KVStringPair>& providedAttrs
, const unsigned int attCount
, XMLElementDecl* elemDecl
, RefVectorOf<XMLAttr>& toFill)
{
// Ask the element to clear the 'provided' flag on all of the att defs
// that it owns, and to return us a boolean indicating whether it has
// any defs.
const bool hasDefs = elemDecl->resetDefs();
// If there are no expliclitily provided attributes and there are no
// defined attributes for the element, the we don't have anything to do.
// So just return zero in this case.
if (!hasDefs && !attCount)
return 0;
// Keep up with how many attrs we end up with total
unsigned int retCount = 0;
// And get the current size of the output vector. This lets us use
// existing elements until we fill it, then start adding new ones.
const unsigned int curAttListSize = toFill.size();
// We need a buffer into which raw scanned attribute values will be
// normalized.
XMLBufBid bbNormal(&fBufMgr);
XMLBuffer& normBuf = bbNormal.getBuffer();
// Loop through our explicitly provided attributes, which are in the raw
// scanned form, and build up XMLAttr objects.
unsigned int index;
for (index = 0; index < attCount; index++)
{
const KVStringPair* curPair = providedAttrs.elementAt(index);
// We have to split the name into its prefix and name parts. Then
// we map the prefix to its URI.
const XMLCh* const namePtr = curPair->getKey();
ArrayJanitor<XMLCh> janName(0);
// use a stack-based buffer when possible.
XMLCh tempBuffer[100];
const int colonInd = XMLString::indexOf(namePtr, chColon);
const XMLCh* prefPtr = XMLUni::fgZeroLenString;
const XMLCh* suffPtr = XMLUni::fgZeroLenString;
if (colonInd != -1)
{
// We have to split the string, so make a copy.
if (XMLString::stringLen(namePtr) < sizeof(tempBuffer) / sizeof(tempBuffer[0]))
{
XMLString::copyString(tempBuffer, namePtr);
tempBuffer[colonInd] = chNull;
prefPtr = tempBuffer;
}
else
{
janName.reset(XMLString::replicate(namePtr, fMemoryManager), fMemoryManager);
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
janName[colonInd] = chNull;
prefPtr = janName.get();
}
suffPtr = prefPtr + colonInd + 1;
}
else
{
// No colon, so we just have a name with no prefix
suffPtr = namePtr;
}
// Map the prefix to a URI id. We tell him that we are mapping an
// attr prefix, so any xmlns attrs at this level will not affect it.
const unsigned int uriId = resolvePrefix(prefPtr, ElemStack::Mode_Attribute);
// If the uri comes back as the xmlns or xml URI or its just a name
// and that name is 'xmlns', then we handle it specially. So set a
// boolean flag that lets us quickly below know which we are dealing
// with.
const bool isNSAttr = (uriId == fXMLNSNamespaceId)
|| (uriId == fXMLNamespaceId)
|| XMLString::equals(suffPtr, XMLUni::fgXMLNSString)
|| XMLString::equals(getURIText(uriId), SchemaSymbols::fgURI_XSI);
// If its not a special case namespace attr of some sort, then we
// do normal checking and processing.
XMLAttDef::AttTypes attType;
if (!isNSAttr || fGrammarType == Grammar::DTDGrammarType)
{
// Some checking for attribute wild card first (for schema)
bool laxThisOne = false;
bool skipThisOne = false;
XMLAttDef* attDefForWildCard = 0;
XMLAttDef* attDef = 0;
if (fGrammarType == Grammar::SchemaGrammarType) {
//retrieve the att def
attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(suffPtr, uriId);
// if not found or faulted in - check for a matching wildcard attribute
// if no matching wildcard attribute, check (un)qualifed cases and flag
// appropriate errors
if (!attDef || (attDef->getCreateReason() == XMLAttDef::JustFaultIn)) {
SchemaAttDef* attWildCard = ((SchemaElementDecl*)elemDecl)->getAttWildCard();
if (attWildCard) {
//if schema, see if we should lax or skip the validation of this attribute
if (anyAttributeValidation(attWildCard, uriId, skipThisOne, laxThisOne)) {
SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(getURIText(uriId));
if (sGrammar && sGrammar->getGrammarType() == Grammar::SchemaGrammarType) {
RefHashTableOf<XMLAttDef>* attRegistry = sGrammar->getAttributeDeclRegistry();
if (attRegistry) {
attDefForWildCard = attRegistry->get(suffPtr);
}
}
}
}
else {
// not found, see if the attDef should be qualified or not
if (uriId == fEmptyNamespaceId) {
attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(suffPtr, fURIStringPool->getId(fGrammar->getTargetNamespace()));
if (fValidate
&& attDef
&& attDef->getCreateReason() != XMLAttDef::JustFaultIn) {
// the attribute should be qualified
fValidator->emitError
(
XMLValid::AttributeNotQualified
, attDef->getFullName()
);
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)(attDef))->setValidity(PSVIDefs::INVALID);
}
}
}
else {
attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(suffPtr, fEmptyNamespaceId);
if (fValidate
&& attDef
&& attDef->getCreateReason() != XMLAttDef::JustFaultIn) {
// the attribute should be qualified
fValidator->emitError
(
XMLValid::AttributeNotUnQualified
, attDef->getFullName()
);
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)(attDef))->setValidity(PSVIDefs::INVALID);
}
}
}
}
}
}
// Find this attribute within the parent element. We pass both
// the uriID/name and the raw QName buffer, since we don't know
// how the derived validator and its elements store attributes.
bool wasAdded = false;
if (!attDef) {
attDef = elemDecl->findAttr
(
curPair->getKey()
, uriId
, suffPtr
, prefPtr
, XMLElementDecl::AddIfNotFound
, wasAdded
);
}
Gareth Reakes
committed
if(!skipThisOne && fGrammarType == Grammar::SchemaGrammarType) {
//we may have set it to invalid already, but this is the first time we are guarenteed to have the attDef
if(((SchemaAttDef *)(attDef))->getValidity() != PSVIDefs::INVALID)
((SchemaAttDef *)(attDef))->setValidity(PSVIDefs::VALID);
Gareth Reakes
committed
((SchemaAttDef *)(attDef))->setValidationAttempted(PSVIDefs::FULL);
}
if (wasAdded)
{
// This is to tell the Validator that this attribute was
// faulted-in, was not an attribute in the attdef originally
attDef->setCreateReason(XMLAttDef::JustFaultIn);
}
bool errorCondition = fValidate && !attDefForWildCard &&
Gareth Reakes
committed
attDef->getCreateReason() == XMLAttDef::JustFaultIn && !attDef->getProvided();
if (errorCondition && !skipThisOne && !laxThisOne)
{
//
// Its not valid for this element, so issue an error if we are
// validating.
//
XMLBufBid bbMsg(&fBufMgr);
XMLBuffer& bufMsg = bbMsg.getBuffer();
if (uriId != fEmptyNamespaceId) {
XMLBufBid bbURI(&fBufMgr);
XMLBuffer& bufURI = bbURI.getBuffer();
getURIText(uriId, bufURI);
bufMsg.append(chOpenCurly);
bufMsg.append(bufURI.getRawBuffer());
bufMsg.append(chCloseCurly);
}
bufMsg.append(suffPtr);
fValidator->emitError
(
XMLValid::AttNotDefinedForElement
, bufMsg.getRawBuffer()
, elemDecl->getFullName()
);
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)(attDef))->setValidity(PSVIDefs::INVALID);
}
Gareth Reakes
committed
else if(errorCondition && laxThisOne && fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)(attDef))->setValidationAttempted(PSVIDefs::NONE);
((SchemaAttDef *)(attDef))->setValidity(PSVIDefs::UNKNOWN);
}
// If its already provided, then there are more than one of
// this attribute in this start tag, so emit an error.
if (attDef->getProvided())
{
emitError
(
XMLErrs::AttrAlreadyUsedInSTag
, attDef->getFullName()
, elemDecl->getFullName()
);
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)(attDef))->setValidity(PSVIDefs::INVALID);
}
}
else
{
attDef->setProvided(true);
}
// Now normalize the raw value since we have the attribute type. We
// don't care about the return status here. If it failed, an error
// was issued, which is all we care about.
if (attDefForWildCard) {
Gareth Reakes
committed
((SchemaAttDef*)attDef)->setAnyDatatypeValidator(((SchemaAttDef*) attDefForWildCard)->getDatatypeValidator());
normalizeAttValue
(
attDefForWildCard
, curPair->getValue()
, normBuf
);
// If we found an attdef for this one, then lets validate it.
if (fNormalizeData)
{
DatatypeValidator* tempDV = ((SchemaAttDef*) attDefForWildCard)->getDatatypeValidator();
if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
{
// normalize the attribute according to schema whitespace facet
XMLBufBid bbtemp(&fBufMgr);
XMLBuffer& tempBuf = bbtemp.getBuffer();
((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, normBuf.getRawBuffer(), tempBuf);
normBuf.set(tempBuf.getRawBuffer());
}
}
if (fValidate && !skipThisOne) {
fValidator->validateAttrValue
(
attDefForWildCard
, normBuf.getRawBuffer()
, false
, elemDecl
);
}
// Save the type for later use
attType = attDefForWildCard->getType();
if(fGrammarType == Grammar::SchemaGrammarType) {
Gareth Reakes
committed
((SchemaElementDecl *)(elemDecl))->updateValidityFromAttribute((SchemaAttDef *)attDef);
DatatypeValidator* tempDV = ((SchemaAttDef*) attDefForWildCard)->getDatatypeValidator();
if(tempDV && tempDV->getType() == DatatypeValidator::Union)
((SchemaAttDef*)attDef)->setMembertypeValidator(((UnionDatatypeValidator *)tempDV)->getMemberTypeValidator());
}
}
else {
normalizeAttValue
(
attDef
, curPair->getValue()
, normBuf
);
// If we found an attdef for this one, then lets validate it.
if (attDef->getCreateReason() != XMLAttDef::JustFaultIn)
{
if (fNormalizeData && (fGrammarType == Grammar::SchemaGrammarType))
{
DatatypeValidator* tempDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();
if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
{
// normalize the attribute according to schema whitespace facet
XMLBufBid bbtemp(&fBufMgr);
XMLBuffer& tempBuf = bbtemp.getBuffer();
((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, normBuf.getRawBuffer(), tempBuf);
normBuf.set(tempBuf.getRawBuffer());
}
}
if (fValidate && !skipThisOne)
{
fValidator->validateAttrValue
(
attDef
, normBuf.getRawBuffer()
, false
, elemDecl
);
}
}
// Save the type for later use
attType = attDef->getType();
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType)
((SchemaElementDecl *)(elemDecl))->updateValidityFromAttribute((SchemaAttDef *)attDef);
}
}
else
{
// Just normalize as CDATA
attType = XMLAttDef::CData;
normalizeAttRawValue
(
curPair->getKey()
, curPair->getValue()
, normBuf
);
}
// Add this attribute to the attribute list that we use to pass them
// to the handler. We reuse its existing elements but expand it as
// required.
XMLAttr* curAttr;
Gareth Reakes
committed
// check for duplicate namespace attributes:
// by checking for qualified names with the same local part and with prefixes
// which have been bound to namespace names that are identical.
if (fGrammarType == Grammar::DTDGrammarType) {
for (unsigned int attrIndex=0; attrIndex < retCount; attrIndex++) {
curAttr = toFill.elementAt(attrIndex);
if (uriId == curAttr->getURIId() &&
XMLString::equals(suffPtr, curAttr->getName())) {
emitError
(
XMLErrs::AttrAlreadyUsedInSTag
, curAttr->getName()
, elemDecl->getFullName()
);
}
}
}
curAttr = new (fMemoryManager) XMLAttr
(
uriId
, suffPtr
, prefPtr
, normBuf.getRawBuffer()
, attType
, true
, fMemoryManager
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
);
toFill.addElement(curAttr);
}
else
{
curAttr = toFill.elementAt(retCount);
curAttr->set
(
uriId
, suffPtr
, prefPtr
, normBuf.getRawBuffer()
, attType
);
curAttr->setSpecified(true);
}
// Bump the count of attrs in the list
retCount++;
}
// Now, if there are any attributes declared by this element, let's
// go through them and make sure that any required ones are provided,
// and fault in any fixed ones and defaulted ones that are not provided
// literally.
if (hasDefs)
{
// Check after all specified attrs are scanned
// (1) report error for REQUIRED attrs that are missing (V_TAGc)
// (2) add default attrs if missing (FIXED and NOT_FIXED)
XMLAttDefList& attDefList = elemDecl->getAttDefList();
while (attDefList.hasMoreElements())
{
// Get the current att def, for convenience and its def type
Gareth Reakes
committed
const XMLAttDef *curDef = &attDefList.nextElement();
const XMLAttDef::DefAttTypes defType = curDef->getDefaultType();
Gareth Reakes
committed
if (!curDef->getProvided())
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)curDef)->setValidationAttempted(PSVIDefs::FULL);
((SchemaAttDef *)curDef)->setValidity(PSVIDefs::VALID);
}
//the attributes is not provided
if (fValidate)
{
// If we are validating and its required, then an error
if ((defType == XMLAttDef::Required) ||
(defType == XMLAttDef::Required_And_Fixed) )
{
fValidator->emitError
(
XMLValid::RequiredAttrNotProvided
Gareth Reakes
committed
, curDef->getFullName()
if(fGrammarType == Grammar::SchemaGrammarType)
Gareth Reakes
committed
((SchemaAttDef *)(curDef))->setValidity(PSVIDefs::INVALID);
}
else if ((defType == XMLAttDef::Default) ||
(defType == XMLAttDef::Fixed) )
{
Gareth Reakes
committed
if (fStandalone && curDef->isExternal())
{
// XML 1.0 Section 2.9
// Document is standalone, so attributes must not be defaulted.
fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef->getFullName(), elemDecl->getFullName());
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType)
((SchemaAttDef *)(curDef))->setValidity(PSVIDefs::INVALID);
}
}
}
// Fault in the value if needed, and bump the att count.
// We have to
if ((defType == XMLAttDef::Default)
|| (defType == XMLAttDef::Fixed))
{
// Let the validator pass judgement on the attribute value
if (fValidate)
{
fValidator->validateAttrValue
(
Gareth Reakes
committed
curDef
, curDef->getValue()
, false
, elemDecl
);
}
XMLAttr* curAtt;
if (retCount >= curAttListSize)
{
curAtt = new (fMemoryManager) XMLAttr(fMemoryManager);
Gareth Reakes
committed
fValidator->faultInAttr(*curAtt, *curDef);
fAttrList->addElement(curAtt);
}
else
{
curAtt = fAttrList->elementAt(retCount);
Gareth Reakes
committed
fValidator->faultInAttr(*curAtt, *curDef);
}
if (fGrammarType == Grammar::DTDGrammarType)
{
// Map the new attribute's prefix to a URI id and store
// that in the attribute object.
curAtt->setURIId
(
resolvePrefix(curAtt->getPrefix(), ElemStack::Mode_Attribute)
);
}
// Indicate it was not explicitly specified and bump count
curAtt->setSpecified(false);
retCount++;
}
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType)
((SchemaElementDecl *)elemDecl)->updateValidityFromAttribute((SchemaAttDef *)curDef);
}
else
{
//attribute is provided
// (schema) report error for PROHIBITED attrs that are present (V_TAGc)
Gareth Reakes
committed
if (defType == XMLAttDef::Prohibited && fValidate) {
fValidator->emitError
(
XMLValid::ProhibitedAttributePresent
Gareth Reakes
committed
, curDef->getFullName()
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)(curDef))->setValidity(PSVIDefs::INVALID);
((SchemaElementDecl *)elemDecl)->updateValidityFromAttribute((SchemaAttDef *)curDef);
}
}
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
}
}
}
return retCount;
}
// This method will take a raw attribute value and normalize it according to
// the rules of the attribute type. It will put the resulting value into the
// passed buffer.
//
// This code assumes that escaped characters in the original value (via char
// refs) are prefixed by a 0xFFFF character. This is because some characters
// are legal if escaped only. And some escape chars are not subject to
// normalization rules.
bool IGXMLScanner::normalizeAttValue( const XMLAttDef* const attDef
, const XMLCh* const value
, XMLBuffer& toFill)
{
// A simple state value for a whitespace processing state machine
enum States
{
InWhitespace
, InContent
};
// Get the type and name
const XMLAttDef::AttTypes type = attDef->getType();
// Assume its going to go fine, and empty the target buffer in preperation
bool retVal = true;
toFill.reset();
// Get attribute def - to check to see if it's declared externally or not
bool isAttExternal = attDef->isExternal();
// Loop through the chars of the source value and normalize it according
// to the type.
States curState = InContent;
bool escaped;
bool firstNonWS = false;
XMLCh nextCh;
const XMLCh* srcPtr = value;
while (*srcPtr)
{
// Get the next character from the source. We have to watch for
// escaped characters (which are indicated by a 0xFFFF value followed
// by the char that was escaped.)
nextCh = *srcPtr;
escaped = (nextCh == 0xFFFF);
if (escaped)
nextCh = *++srcPtr;
// If its not escaped, then make sure its not a < character, which is
// not allowed in attribute values.
if (!escaped && (*srcPtr == chOpenAngle))
{
emitError(XMLErrs::BracketInAttrValue, attDef->getFullName());
retVal = false;
}
if (type == XMLAttDef::CData || type > XMLAttDef::Notation)
{
if (!escaped)
{
if ((nextCh == 0x09) || (nextCh == 0x0A) || (nextCh == 0x0D))
{
// Check Validity Constraint for Standalone document declaration
// XML 1.0, Section 2.9
if (fStandalone && fValidate && isAttExternal)
{
// Can't have a standalone document declaration of "yes" if attribute
// values are subject to normalisation
fValidator->emitError(XMLValid::NoAttNormForStandalone, attDef->getFullName());
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)(attDef))->setValidity(PSVIDefs::INVALID);
}
}
nextCh = chSpace;
}
}
}
else
{
if (curState == InWhitespace)
{
{
if (firstNonWS)
toFill.append(chSpace);
curState = InContent;
firstNonWS = true;
}
else
{
srcPtr++;
continue;
}
}
else if (curState == InContent)
{
{
curState = InWhitespace;
srcPtr++;
// Check Validity Constraint for Standalone document declaration
// XML 1.0, Section 2.9
if (fStandalone && fValidate && isAttExternal)
{
if (!firstNonWS || (nextCh != chSpace) || (!*srcPtr) || fReaderMgr.getCurrentReader()->isWhitespace(*srcPtr))
Gareth Reakes
committed
// Can't have a standalone document declaration of "yes" if attribute
// values are subject to normalisation
fValidator->emitError(XMLValid::NoAttNormForStandalone, attDef->getFullName());
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType) {
((SchemaAttDef *)(attDef))->setValidity(PSVIDefs::INVALID);
}
}
}
continue;
}
firstNonWS = true;
}
}
// Add this char to the target buffer
toFill.append(nextCh);
// And move up to the next character in the source
srcPtr++;
}
Gareth Reakes
committed
if(fGrammarType == Grammar::SchemaGrammarType)
((SchemaElementDecl *)fElemStack.topElement()->fThisElement)->updateValidityFromAttribute((SchemaAttDef *)attDef);
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
return retVal;
}
// This method will just normalize the input value as CDATA without
// any standalone checking.
bool IGXMLScanner::normalizeAttRawValue( const XMLCh* const attrName
, const XMLCh* const value
, XMLBuffer& toFill)
{
// Assume its going to go fine, and empty the target buffer in preperation
bool retVal = true;
toFill.reset();
// Loop through the chars of the source value and normalize it according
// to the type.
bool escaped;
XMLCh nextCh;
const XMLCh* srcPtr = value;
while (*srcPtr)
{
// Get the next character from the source. We have to watch for
// escaped characters (which are indicated by a 0xFFFF value followed
// by the char that was escaped.)
nextCh = *srcPtr;
escaped = (nextCh == 0xFFFF);
if (escaped)
nextCh = *++srcPtr;
// If its not escaped, then make sure its not a < character, which is
// not allowed in attribute values.
if (!escaped && (*srcPtr == chOpenAngle))
{
emitError(XMLErrs::BracketInAttrValue, attrName);
retVal = false;
}
if (!escaped)
{
// NOTE: Yes this is a little redundant in that a 0x20 is
// replaced with an 0x20. But its faster to do this (I think)
// than checking for 9, A, and D separately.
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
nextCh = chSpace;
}
// Add this char to the target buffer
toFill.append(nextCh);
// And move up to the next character in the source
srcPtr++;
}
return retVal;
}
unsigned int
IGXMLScanner::resolvePrefix( const XMLCh* const prefix
, const ElemStack::MapModes mode)
{
// Watch for the special namespace prefixes. We always map these to
// special URIs. 'xml' gets mapped to the official URI that its defined
// to map to by the NS spec. xmlns gets mapped to a special place holder
// URI that we define (so that it maps to something checkable.)
if (XMLString::equals(prefix, XMLUni::fgXMLNSString))
return fXMLNSNamespaceId;
else if (XMLString::equals(prefix, XMLUni::fgXMLString))
return fXMLNamespaceId;
// Ask the element stack to search up itself for a mapping for the
// passed prefix.
bool unknown;
unsigned int uriId = fElemStack.mapPrefixToURI(prefix, mode, unknown);
// If it was unknown, then the URI was faked in but we have to issue an error
if (unknown)
emitError(XMLErrs::UnknownPrefix, prefix);
return uriId;
}
unsigned int
IGXMLScanner::resolvePrefix( const XMLCh* const prefix
, XMLBuffer& bufToFill
, const ElemStack::MapModes mode)
{
// Watch for the special namespace prefixes. We always map these to
// special URIs. 'xml' gets mapped to the official URI that its defined
// to map to by the NS spec. xmlns gets mapped to a special place holder
// URI that we define (so that it maps to something checkable.)
if (XMLString::equals(prefix, XMLUni::fgXMLNSString))
return fXMLNSNamespaceId;
else if (XMLString::equals(prefix, XMLUni::fgXMLString))
return fXMLNamespaceId;
// Ask the element stack to search up itself for a mapping for the
// passed prefix.
bool unknown;
unsigned int uriId = fElemStack.mapPrefixToURI(prefix, mode, unknown);
// If it was unknown, then the URI was faked in but we have to issue an error
if (unknown)
emitError(XMLErrs::UnknownPrefix, prefix);
getURIText(uriId,bufToFill);
return uriId;
}
// This method will reset the scanner data structures, and related plugged
// in stuff, for a new scan session. We get the input source for the primary
// XML entity, create the reader for it, and push it on the stack so that
// upon successful return from here we are ready to go.
void IGXMLScanner::scanReset(const InputSource& src)
{
// This call implicitly tells us that we are going to reuse the scanner
// if it was previously used. So tell the validator to reset itself.
//
// But, if the fUseCacheGrammar flag is set, then don't reset it.
//
// NOTE: The ReaderMgr is flushed on the way out, because that is
// required to insure that files are closed.
fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar);
fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar);
fDTDGrammar = (DTDGrammar*) fGrammarResolver->getGrammar(XMLUni::fgDTDEntityString);
if (!fDTDGrammar) {
fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager);
fGrammarResolver->putGrammar(fDTDGrammar);
}
else
fDTDGrammar->reset();
fGrammar = fDTDGrammar;
fGrammarType = fGrammar->getGrammarType();
fRootGrammar = 0;
if (fValidatorFromUser) {
if (fValidator->handlesDTD())
fValidator->setGrammar(fGrammar);
else if (fValidator->handlesSchema()) {
((SchemaValidator*) fValidator)->setErrorReporter(fErrorReporter);
((SchemaValidator*) fValidator)->setGrammarResolver(fGrammarResolver);
((SchemaValidator*) fValidator)->setExitOnFirstFatal(fExitOnFirstFatal);
}
}
else {
// set fValidator as fDTDValidator
fValidator = fDTDValidator;
fValidator->setGrammar(fGrammar);
}
// Reset validation
fValidate = (fValScheme == Val_Always) ? true : false;
// And for all installed handlers, send reset events. This gives them
// a chance to flush any cached data.
if (fDocHandler)
fDocHandler->resetDocument();
if (fEntityHandler)
fEntityHandler->resetEntities();
if (fErrorReporter)
fErrorReporter->resetErrors();
// Clear out the id reference list
fIDRefList->removeAll();
// Reset the Root Element Name
fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName;
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
fRootElemName = 0;
// Reset IdentityConstraints
fValueStoreCache->startDocument();
fMatcherStack->clear();
// Reset the element stack, and give it the latest ids for the special
// URIs it has to know about.
fElemStack.reset
(
fEmptyNamespaceId
, fUnknownNamespaceId
, fXMLNamespaceId
, fXMLNSNamespaceId
);
if (!fSchemaNamespaceId)
fSchemaNamespaceId = fURIStringPool->addOrFind(SchemaSymbols::fgURI_XSI);
// Reset some status flags
fInException = false;
fStandalone = false;
fErrorCount = 0;
fHasNoDTD = true;
fSeeXsi = false;
// Reset the validators
fDTDValidator->reset();
fDTDValidator->setErrorReporter(fErrorReporter);
fSchemaValidator->reset();
fSchemaValidator->setErrorReporter(fErrorReporter);
fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
fSchemaValidator->setGrammarResolver(fGrammarResolver);
if (fValidatorFromUser)
fValidator->reset();
// Handle the creation of the XML reader object for this input source.
// This will provide us with transcoding and basic lexing services.
XMLReader* newReader = fReaderMgr.createReader
(
src
, true
, XMLReader::RefFrom_NonLiteral
, XMLReader::Type_General
, XMLReader::Source_External
, fCalculateSrcOfs
);
if (!newReader) {
if (src.getIssueFatalErrorIfNotFound())
ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId());
else
ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId());
}
// Push this read onto the reader manager
fReaderMgr.pushReader(newReader, 0);
// and reset security-related things if necessary:
if(fSecurityManager != 0)