author | chegar |
Sun, 17 Aug 2014 15:51:56 +0100 | |
changeset 25868 | 686eef1e7a79 |
parent 25591 | jaxp/src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java@8382d4909d6a |
child 29765 | d0707eacc322 |
permissions | -rw-r--r-- |
12005 | 1 |
/* |
22139
f4b2aa462b46
8029236: Update copyright year to match last edit in jdk8 jaxp repository for 2013
joehw
parents:
21470
diff
changeset
|
2 |
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
12005 | 3 |
*/ |
4 |
||
5 |
/* |
|
6 |
* Copyright 2005 The Apache Software Foundation. |
|
7 |
* |
|
8 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
9 |
* you may not use this file except in compliance with the License. |
|
10 |
* You may obtain a copy of the License at |
|
11 |
* |
|
12 |
* http://www.apache.org/licenses/LICENSE-2.0 |
|
13 |
* |
|
14 |
* Unless required by applicable law or agreed to in writing, software |
|
15 |
* distributed under the License is distributed on an "AS IS" BASIS, |
|
16 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
17 |
* See the License for the specific language governing permissions and |
|
18 |
* limitations under the License. |
|
19 |
*/ |
|
20 |
||
21 |
package com.sun.org.apache.xerces.internal.impl; |
|
22 |
||
23 |
import java.io.IOException; |
|
24 |
import com.sun.org.apache.xerces.internal.xni.XMLString; |
|
25 |
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidatorFilter; |
|
26 |
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; |
|
27 |
import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; |
|
28 |
import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl; |
|
29 |
import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; |
|
30 |
import com.sun.org.apache.xerces.internal.util.XMLSymbols; |
|
31 |
import com.sun.org.apache.xerces.internal.xni.NamespaceContext; |
|
32 |
import com.sun.org.apache.xerces.internal.xni.QName; |
|
33 |
import com.sun.org.apache.xerces.internal.xni.XNIException; |
|
34 |
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; |
|
35 |
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; |
|
36 |
import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; |
|
37 |
import com.sun.org.apache.xerces.internal.xni.XMLAttributes; |
|
38 |
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; |
|
39 |
import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; |
|
40 |
||
41 |
import javax.xml.stream.XMLInputFactory; |
|
42 |
import javax.xml.stream.XMLStreamConstants; |
|
43 |
import javax.xml.stream.events.XMLEvent; |
|
44 |
||
45 |
/** |
|
46 |
* This class adds the functionality of namespace processing. |
|
47 |
* |
|
48 |
* This class has been modified as per the new design which is more suited to |
|
49 |
* efficiently build pull parser. Lot of improvements have been done and |
|
50 |
* the code has been added to support stax functionality/features. |
|
51 |
* |
|
52 |
* |
|
53 |
* This class scans an XML document, checks if document has a DTD, and if |
|
54 |
* DTD is not found the scanner will remove the DTD Validator from the pipeline and perform |
|
55 |
* namespace binding. |
|
56 |
* |
|
57 |
* |
|
58 |
* @author Neeraj Bajaj, Sun Microsystems |
|
59 |
* @author Venugopal Rao K, Sun Microsystems |
|
60 |
* @author Elena Litani, IBM |
|
61 |
*/ |
|
62 |
public class XMLNSDocumentScannerImpl |
|
63 |
extends XMLDocumentScannerImpl { |
|
64 |
||
65 |
/** |
|
66 |
* If is true, the dtd validator is no longer in the pipeline |
|
67 |
* and the scanner should bind namespaces |
|
68 |
*/ |
|
69 |
protected boolean fBindNamespaces; |
|
70 |
||
71 |
/** If validating parser, make sure we report an error in the |
|
72 |
* scanner if DTD grammar is missing.*/ |
|
73 |
protected boolean fPerformValidation; |
|
74 |
||
75 |
||
76 |
/** Default value of this feature is false, when in Stax mode this should be true */ |
|
77 |
protected boolean fNotAddNSDeclAsAttribute = false; |
|
78 |
||
79 |
/** DTD validator */ |
|
80 |
private XMLDTDValidatorFilter fDTDValidator; |
|
81 |
||
82 |
/** xmlns, default Namespace, declared */ |
|
83 |
private boolean fXmlnsDeclared = false; |
|
84 |
||
85 |
/** Resets the fields of this scanner. |
|
86 |
*/ |
|
87 |
public void reset(PropertyManager propertyManager) { |
|
88 |
setPropertyManager(propertyManager); |
|
89 |
super.reset(propertyManager); |
|
90 |
fBindNamespaces = false; |
|
91 |
fNotAddNSDeclAsAttribute = !((Boolean)propertyManager.getProperty(Constants.ADD_NAMESPACE_DECL_AS_ATTRIBUTE)).booleanValue(); |
|
92 |
} |
|
93 |
||
94 |
public void reset(XMLComponentManager componentManager) |
|
95 |
throws XMLConfigurationException { |
|
96 |
super.reset(componentManager); |
|
97 |
fNotAddNSDeclAsAttribute = false ; |
|
98 |
fPerformValidation = false; |
|
99 |
fBindNamespaces = false; |
|
100 |
} |
|
101 |
||
102 |
/** return the next state on the input |
|
103 |
* |
|
104 |
* @return int |
|
105 |
*/ |
|
106 |
||
107 |
public int next() throws IOException, XNIException { |
|
108 |
//since namespace context should still be valid when the parser is at the end element state therefore |
|
109 |
//we pop the context only when next() has been called after the end element state was encountered. - nb. |
|
110 |
||
111 |
if((fScannerLastState == XMLEvent.END_ELEMENT) && fBindNamespaces){ |
|
112 |
fScannerLastState = -1; |
|
113 |
fNamespaceContext.popContext(); |
|
114 |
} |
|
115 |
||
116 |
return fScannerLastState = super.next(); |
|
117 |
} |
|
118 |
||
119 |
/** |
|
120 |
* The scanner is responsible for removing DTD validator |
|
121 |
* from the pipeline if it is not needed. |
|
122 |
* |
|
123 |
* @param previous The filter component before DTDValidator |
|
124 |
* @param dtdValidator |
|
125 |
* The DTDValidator |
|
126 |
* @param next The documentHandler after the DTDValidator |
|
127 |
*/ |
|
128 |
public void setDTDValidator(XMLDTDValidatorFilter dtd){ |
|
129 |
fDTDValidator = dtd; |
|
130 |
} |
|
131 |
||
132 |
||
133 |
||
134 |
/** |
|
135 |
* Scans a start element. This method will handle the binding of |
|
136 |
* namespace information and notifying the handler of the start |
|
137 |
* of the element. |
|
138 |
* <p> |
|
139 |
* <pre> |
|
140 |
* [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' |
|
141 |
* [40] STag ::= '<' Name (S Attribute)* S? '>' |
|
142 |
* </pre> |
|
143 |
* <p> |
|
144 |
* <strong>Note:</strong> This method assumes that the leading |
|
145 |
* '<' character has been consumed. |
|
146 |
* <p> |
|
147 |
* <strong>Note:</strong> This method uses the fElementQName and |
|
148 |
* fAttributes variables. The contents of these variables will be |
|
149 |
* destroyed. The caller should copy important information out of |
|
150 |
* these variables before calling this method. |
|
151 |
* |
|
152 |
* @return True if element is empty. (i.e. It matches |
|
153 |
* production [44]. |
|
154 |
*/ |
|
155 |
protected boolean scanStartElement() |
|
156 |
throws IOException, XNIException { |
|
157 |
||
158 |
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanStartElement()"); |
|
159 |
//when skipping is true and no more elements should be added |
|
160 |
if(fSkip && !fAdd){ |
|
161 |
//get the stored element -- if everything goes right this should match the |
|
162 |
//token in the buffer |
|
163 |
||
164 |
QName name = fElementStack.getNext(); |
|
165 |
||
166 |
if(DEBUG_SKIP_ALGORITHM){ |
|
167 |
System.out.println("Trying to skip String = " + name.rawname); |
|
168 |
} |
|
169 |
||
170 |
//Be conservative -- if skipping fails -- stop. |
|
171 |
fSkip = fEntityScanner.skipString(name.rawname); // skipQElement(name); |
|
172 |
||
173 |
if(fSkip){ |
|
174 |
if(DEBUG_SKIP_ALGORITHM){ |
|
175 |
System.out.println("Element SUCESSFULLY skipped = " + name.rawname); |
|
176 |
} |
|
177 |
fElementStack.push(); |
|
178 |
fElementQName = name; |
|
179 |
}else{ |
|
180 |
//if skipping fails reposition the stack or fallback to normal way of processing |
|
181 |
fElementStack.reposition(); |
|
182 |
if(DEBUG_SKIP_ALGORITHM){ |
|
183 |
System.out.println("Element was NOT skipped, REPOSITIONING stack" ); |
|
184 |
} |
|
185 |
} |
|
186 |
} |
|
187 |
||
188 |
//we are still at the stage of adding elements |
|
189 |
//the elements were not matched or |
|
190 |
//fSkip is not set to true |
|
191 |
if(!fSkip || fAdd){ |
|
192 |
//get the next element from the stack |
|
193 |
fElementQName = fElementStack.nextElement(); |
|
194 |
// There are two variables,fNamespaces and fBindNamespaces |
|
195 |
//StAX uses XMLNSDocumentScannerImpl so this distinction needs to be maintained |
|
196 |
if (fNamespaces) { |
|
197 |
fEntityScanner.scanQName(fElementQName); |
|
198 |
} else { |
|
199 |
String name = fEntityScanner.scanName(); |
|
200 |
fElementQName.setValues(null, name, name, null); |
|
201 |
} |
|
202 |
||
203 |
if(DEBUG)System.out.println("Element scanned in start element is " + fElementQName.toString()); |
|
204 |
if(DEBUG_SKIP_ALGORITHM){ |
|
205 |
if(fAdd){ |
|
206 |
System.out.println("Elements are being ADDED -- elemet added is = " + fElementQName.rawname + " at count = " + fElementStack.fCount); |
|
207 |
} |
|
208 |
} |
|
209 |
||
210 |
} |
|
211 |
||
212 |
//when the elements are being added , we need to check if we are set for skipping the elements |
|
213 |
if(fAdd){ |
|
214 |
//this sets the value of fAdd variable |
|
215 |
fElementStack.matchElement(fElementQName); |
|
216 |
} |
|
217 |
||
218 |
//xxx: We dont need another pointer, fCurrentElement, we can use fElementQName |
|
219 |
fCurrentElement = fElementQName; |
|
220 |
||
221 |
String rawname = fElementQName.rawname; |
|
25591 | 222 |
checkDepth(rawname); |
12005 | 223 |
if (fBindNamespaces) { |
224 |
fNamespaceContext.pushContext(); |
|
225 |
if (fScannerState == SCANNER_STATE_ROOT_ELEMENT) { |
|
226 |
if (fPerformValidation) { |
|
227 |
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
228 |
"MSG_GRAMMAR_NOT_FOUND", |
|
229 |
new Object[]{ rawname}, |
|
230 |
XMLErrorReporter.SEVERITY_ERROR); |
|
231 |
||
232 |
if (fDoctypeName == null || !fDoctypeName.equals(rawname)) { |
|
233 |
fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN, |
|
234 |
"RootElementTypeMustMatchDoctypedecl", |
|
235 |
new Object[]{fDoctypeName, rawname}, |
|
236 |
XMLErrorReporter.SEVERITY_ERROR); |
|
237 |
} |
|
238 |
} |
|
239 |
} |
|
240 |
} |
|
241 |
||
242 |
||
243 |
fEmptyElement = false; |
|
244 |
fAttributes.removeAllAttributes(); |
|
245 |
||
246 |
if(!seekCloseOfStartTag()){ |
|
247 |
fReadingAttributes = true; |
|
248 |
fAttributeCacheUsedCount =0; |
|
249 |
fStringBufferIndex =0; |
|
250 |
fAddDefaultAttr = true; |
|
251 |
fXmlnsDeclared = false; |
|
252 |
||
253 |
do { |
|
254 |
scanAttribute(fAttributes); |
|
20968 | 255 |
if (fSecurityManager != null && (!fSecurityManager.isNoLimit(fElementAttributeLimit)) && |
256 |
fAttributes.getLength() > fElementAttributeLimit){ |
|
12005 | 257 |
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
258 |
"ElementAttributeLimit", |
|
21470 | 259 |
new Object[]{rawname, fElementAttributeLimit }, |
12005 | 260 |
XMLErrorReporter.SEVERITY_FATAL_ERROR ); |
261 |
} |
|
262 |
||
263 |
} while (!seekCloseOfStartTag()); |
|
264 |
fReadingAttributes=false; |
|
265 |
} |
|
266 |
||
267 |
if (fBindNamespaces) { |
|
268 |
// REVISIT: is it required? forbit xmlns prefix for element |
|
269 |
if (fElementQName.prefix == XMLSymbols.PREFIX_XMLNS) { |
|
270 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
271 |
"ElementXMLNSPrefix", |
|
272 |
new Object[]{fElementQName.rawname}, |
|
273 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
274 |
} |
|
275 |
||
276 |
// bind the element |
|
277 |
String prefix = fElementQName.prefix != null |
|
278 |
? fElementQName.prefix : XMLSymbols.EMPTY_STRING; |
|
279 |
// assign uri to the element |
|
280 |
fElementQName.uri = fNamespaceContext.getURI(prefix); |
|
281 |
// make sure that object in the element stack is updated as well |
|
282 |
fCurrentElement.uri = fElementQName.uri; |
|
283 |
||
284 |
if (fElementQName.prefix == null && fElementQName.uri != null) { |
|
285 |
fElementQName.prefix = XMLSymbols.EMPTY_STRING; |
|
286 |
} |
|
287 |
if (fElementQName.prefix != null && fElementQName.uri == null) { |
|
288 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
289 |
"ElementPrefixUnbound", |
|
290 |
new Object[]{fElementQName.prefix, fElementQName.rawname}, |
|
291 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
292 |
} |
|
293 |
||
294 |
// bind attributes (xmlns are already bound bellow) |
|
295 |
int length = fAttributes.getLength(); |
|
296 |
// fLength = 0; //initialize structure |
|
297 |
for (int i = 0; i < length; i++) { |
|
298 |
fAttributes.getName(i, fAttributeQName); |
|
299 |
||
300 |
String aprefix = fAttributeQName.prefix != null |
|
301 |
? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING; |
|
302 |
String uri = fNamespaceContext.getURI(aprefix); |
|
303 |
// REVISIT: try removing the first "if" and see if it is faster. |
|
304 |
// |
|
305 |
if (fAttributeQName.uri != null && fAttributeQName.uri == uri) { |
|
306 |
// checkDuplicates(fAttributeQName, fAttributes); |
|
307 |
continue; |
|
308 |
} |
|
309 |
if (aprefix != XMLSymbols.EMPTY_STRING) { |
|
310 |
fAttributeQName.uri = uri; |
|
311 |
if (uri == null) { |
|
312 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
313 |
"AttributePrefixUnbound", |
|
314 |
new Object[]{fElementQName.rawname,fAttributeQName.rawname,aprefix}, |
|
315 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
316 |
} |
|
317 |
fAttributes.setURI(i, uri); |
|
318 |
// checkDuplicates(fAttributeQName, fAttributes); |
|
319 |
} |
|
320 |
} |
|
321 |
||
322 |
if (length > 1) { |
|
323 |
QName name = fAttributes.checkDuplicatesNS(); |
|
324 |
if (name != null) { |
|
325 |
if (name.uri != null) { |
|
326 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
327 |
"AttributeNSNotUnique", |
|
328 |
new Object[]{fElementQName.rawname, name.localpart, name.uri}, |
|
329 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
330 |
} else { |
|
331 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
332 |
"AttributeNotUnique", |
|
333 |
new Object[]{fElementQName.rawname, name.rawname}, |
|
334 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
335 |
} |
|
336 |
} |
|
337 |
} |
|
338 |
} |
|
339 |
||
340 |
||
341 |
if (fEmptyElement) { |
|
342 |
//decrease the markup depth.. |
|
343 |
fMarkupDepth--; |
|
344 |
||
345 |
// check that this element was opened in the same entity |
|
346 |
if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) { |
|
347 |
reportFatalError("ElementEntityMismatch", |
|
348 |
new Object[]{fCurrentElement.rawname}); |
|
349 |
} |
|
350 |
// call handler |
|
351 |
if (fDocumentHandler != null) { |
|
352 |
if(DEBUG) |
|
353 |
System.out.println("emptyElement = " + fElementQName); |
|
354 |
||
355 |
fDocumentHandler.emptyElement(fElementQName, fAttributes, null); |
|
356 |
} |
|
357 |
||
358 |
//We should not be popping out the context here in endELement becaause the namespace context is still |
|
359 |
//valid when parser is at the endElement state. |
|
360 |
fScanEndElement = true; |
|
361 |
//if (fBindNamespaces) { |
|
362 |
// fNamespaceContext.popContext(); |
|
363 |
//} |
|
364 |
||
365 |
//pop the element off the stack.. |
|
366 |
fElementStack.popElement(); |
|
367 |
||
368 |
} else { |
|
369 |
||
370 |
if(dtdGrammarUtil != null) |
|
371 |
dtdGrammarUtil.startElement(fElementQName,fAttributes); |
|
372 |
if(fDocumentHandler != null){ |
|
373 |
//complete element and attributes are traversed in this function so we can send a callback |
|
374 |
//here. |
|
375 |
//<strong>we shouldn't be sending callback in scanDocument()</strong> |
|
376 |
if(DEBUG) |
|
377 |
System.out.println("startElement = " + fElementQName); |
|
378 |
fDocumentHandler.startElement(fElementQName, fAttributes, null); |
|
379 |
} |
|
380 |
} |
|
381 |
||
382 |
||
383 |
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanStartElement(): "+fEmptyElement); |
|
384 |
return fEmptyElement; |
|
385 |
||
386 |
} // scanStartElement():boolean |
|
387 |
||
388 |
||
389 |
||
390 |
/** |
|
391 |
* Scans an attribute. |
|
392 |
* <p> |
|
393 |
* <pre> |
|
394 |
* [41] Attribute ::= Name Eq AttValue |
|
395 |
* </pre> |
|
396 |
* <p> |
|
397 |
* <strong>Note:</strong> This method assumes that the next |
|
398 |
* character on the stream is the first character of the attribute |
|
399 |
* name. |
|
400 |
* <p> |
|
401 |
* <strong>Note:</strong> This method uses the fAttributeQName and |
|
402 |
* fQName variables. The contents of these variables will be |
|
403 |
* destroyed. |
|
404 |
* |
|
405 |
* @param attributes The attributes list for the scanned attribute. |
|
406 |
*/ |
|
407 |
protected void scanAttribute(XMLAttributesImpl attributes) |
|
408 |
throws IOException, XNIException { |
|
409 |
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()"); |
|
410 |
||
411 |
// name |
|
412 |
fEntityScanner.scanQName(fAttributeQName); |
|
413 |
||
414 |
// equals |
|
415 |
fEntityScanner.skipSpaces(); |
|
416 |
if (!fEntityScanner.skipChar('=')) { |
|
417 |
reportFatalError("EqRequiredInAttribute", |
|
418 |
new Object[]{fCurrentElement.rawname,fAttributeQName.rawname}); |
|
419 |
} |
|
420 |
fEntityScanner.skipSpaces(); |
|
421 |
||
422 |
// content |
|
423 |
int attrIndex = 0 ; |
|
424 |
||
425 |
||
426 |
//REVISIT: one more case needs to be included: external PE and standalone is no |
|
427 |
boolean isVC = fHasExternalDTD && !fStandalone; |
|
428 |
||
429 |
// REVISIT: it seems that this function should not take attributes, and length |
|
430 |
//fTempString would store attribute value |
|
431 |
///fTempString2 would store attribute non-normalized value |
|
432 |
||
433 |
//this function doesn't use 'attIndex'. We are adding the attribute later |
|
434 |
//after we have figured out that current attribute is not namespace declaration |
|
435 |
//since scanAttributeValue doesn't use attIndex parameter therefore we |
|
436 |
//can safely add the attribute later.. |
|
437 |
XMLString tmpStr = getString(); |
|
438 |
scanAttributeValue(tmpStr, fTempString2, |
|
439 |
fAttributeQName.rawname, attributes, |
|
440 |
attrIndex, isVC); |
|
441 |
||
442 |
String value = null; |
|
443 |
//fTempString.toString(); |
|
444 |
||
445 |
// record namespace declarations if any. |
|
446 |
if (fBindNamespaces) { |
|
447 |
||
448 |
String localpart = fAttributeQName.localpart; |
|
449 |
String prefix = fAttributeQName.prefix != null |
|
450 |
? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING; |
|
451 |
// when it's of form xmlns="..." or xmlns:prefix="...", |
|
452 |
// it's a namespace declaration. but prefix:xmlns="..." isn't. |
|
453 |
if (prefix == XMLSymbols.PREFIX_XMLNS || |
|
454 |
prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) { |
|
455 |
||
456 |
// get the internalized value of this attribute |
|
457 |
String uri = fSymbolTable.addSymbol(tmpStr.ch,tmpStr.offset,tmpStr.length); |
|
458 |
value = uri; |
|
459 |
// 1. "xmlns" can't be bound to any namespace |
|
460 |
if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) { |
|
461 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
462 |
"CantBindXMLNS", |
|
463 |
new Object[]{fAttributeQName}, |
|
464 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
465 |
} |
|
466 |
||
467 |
// 2. the namespace for "xmlns" can't be bound to any prefix |
|
468 |
if (uri == NamespaceContext.XMLNS_URI) { |
|
469 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
470 |
"CantBindXMLNS", |
|
471 |
new Object[]{fAttributeQName}, |
|
472 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
473 |
} |
|
474 |
||
475 |
// 3. "xml" can't be bound to any other namespace than it's own |
|
476 |
if (localpart == XMLSymbols.PREFIX_XML) { |
|
477 |
if (uri != NamespaceContext.XML_URI) { |
|
478 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
479 |
"CantBindXML", |
|
480 |
new Object[]{fAttributeQName}, |
|
481 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
482 |
} |
|
483 |
} |
|
484 |
// 4. the namespace for "xml" can't be bound to any other prefix |
|
485 |
else { |
|
486 |
if (uri ==NamespaceContext.XML_URI) { |
|
487 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
488 |
"CantBindXML", |
|
489 |
new Object[]{fAttributeQName}, |
|
490 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
491 |
} |
|
492 |
} |
|
493 |
prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING; |
|
494 |
//set it equal to XMLSymbols.PREFIX_XMLNS when namespace declaration |
|
495 |
// is of type xmlns = "..", in this case prefix = "" and localname = XMLSymbols.PREFIX_XMLNS |
|
496 |
//this special behavior is because of dependency on this behavior in DOM components |
|
497 |
if(prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS){ |
|
498 |
fAttributeQName.prefix = XMLSymbols.PREFIX_XMLNS; |
|
499 |
} |
|
500 |
// http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix |
|
501 |
// We should only report an error if there is a prefix, |
|
502 |
// that is, the local part is not "xmlns". -SG |
|
503 |
if (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS) { |
|
504 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
505 |
"EmptyPrefixedAttName", |
|
506 |
new Object[]{fAttributeQName}, |
|
507 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
508 |
} |
|
509 |
||
510 |
// check for duplicate prefix bindings |
|
511 |
if (((com.sun.org.apache.xerces.internal.util.NamespaceSupport) fNamespaceContext).containsPrefixInCurrentContext(prefix)) { |
|
512 |
reportFatalError("AttributeNotUnique", |
|
513 |
new Object[]{fCurrentElement.rawname, |
|
514 |
fAttributeQName.rawname}); |
|
515 |
} |
|
516 |
||
517 |
// declare prefix in context |
|
518 |
boolean declared = fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null); |
|
519 |
||
520 |
// check for duplicate xmlns declarations |
|
521 |
if (!declared) { // by convention, prefix == "xmlns" | "xml" |
|
522 |
// error if duplicate declaration |
|
523 |
if (fXmlnsDeclared) { |
|
524 |
reportFatalError("AttributeNotUnique", |
|
525 |
new Object[]{fCurrentElement.rawname, |
|
526 |
fAttributeQName.rawname}); |
|
527 |
} |
|
528 |
||
529 |
// xmlns declared |
|
530 |
fXmlnsDeclared = true; |
|
531 |
} |
|
532 |
||
533 |
//xerces internals (XSAttributeChecker) has dependency on namespace declaration returned |
|
534 |
//as part of XMLAttributes. |
|
535 |
//addition of namespace declaration to the attribute list is controlled by fNotAddNSDeclAsAttribute |
|
536 |
//feature. This is required in Stax where namespace declarations are not considered as attribute |
|
537 |
||
538 |
if(fNotAddNSDeclAsAttribute){ |
|
539 |
return ; |
|
540 |
} |
|
541 |
} |
|
542 |
} |
|
543 |
||
544 |
//add the attributes to the list of attributes |
|
545 |
if (fBindNamespaces) { |
|
546 |
attrIndex = attributes.getLength(); |
|
547 |
attributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, null); |
|
548 |
} else { |
|
549 |
int oldLen = attributes.getLength(); |
|
550 |
attrIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null); |
|
551 |
||
552 |
// WFC: Unique Att Spec |
|
553 |
if (oldLen == attributes.getLength()) { |
|
554 |
reportFatalError("AttributeNotUnique", |
|
555 |
new Object[]{fCurrentElement.rawname, |
|
556 |
fAttributeQName.rawname}); |
|
557 |
} |
|
558 |
} |
|
559 |
||
560 |
attributes.setValue(attrIndex, value,tmpStr); |
|
561 |
//attributes.setNonNormalizedValue(attrIndex, fTempString2.toString()); |
|
562 |
//removing as we are not using non-normalized values . -Venu |
|
563 |
attributes.setSpecified(attrIndex, true); |
|
564 |
||
565 |
// attempt to bind attribute |
|
566 |
if (fAttributeQName.prefix != null) { |
|
567 |
attributes.setURI(attrIndex, fNamespaceContext.getURI(fAttributeQName.prefix)); |
|
568 |
} |
|
569 |
||
570 |
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanAttribute()"); |
|
571 |
} // scanAttribute(XMLAttributes) |
|
572 |
||
573 |
||
574 |
||
575 |
||
576 |
||
577 |
/** Creates a content driver. */ |
|
578 |
protected Driver createContentDriver() { |
|
579 |
return new NSContentDriver(); |
|
580 |
} // createContentDriver():Driver |
|
581 |
||
582 |
/** |
|
583 |
* Driver to handle content scanning. |
|
584 |
*/ |
|
585 |
protected final class NSContentDriver |
|
586 |
extends ContentDriver { |
|
587 |
/** |
|
588 |
* Scan for root element hook. This method is a hook for |
|
589 |
* subclasses to add code that handles scanning for the root |
|
590 |
* element. This method will also attempt to remove DTD validator |
|
591 |
* from the pipeline, if there is no DTD grammar. If DTD validator |
|
592 |
* is no longer in the pipeline bind namespaces in the scanner. |
|
593 |
* |
|
594 |
* |
|
595 |
* @return True if the caller should stop and return true which |
|
596 |
* allows the scanner to switch to a new scanning |
|
597 |
* driver. A return value of false indicates that |
|
598 |
* the content driver should continue as normal. |
|
599 |
*/ |
|
600 |
protected boolean scanRootElementHook() |
|
601 |
throws IOException, XNIException { |
|
602 |
||
603 |
reconfigurePipeline(); |
|
604 |
if (scanStartElement()) { |
|
605 |
setScannerState(SCANNER_STATE_TRAILING_MISC); |
|
606 |
setDriver(fTrailingMiscDriver); |
|
607 |
return true; |
|
608 |
} |
|
609 |
return false; |
|
610 |
||
611 |
} // scanRootElementHook():boolean |
|
612 |
||
613 |
/** |
|
614 |
* Re-configures pipeline by removing the DTD validator |
|
615 |
* if no DTD grammar exists. If no validator exists in the |
|
616 |
* pipeline or there is no DTD grammar, namespace binding |
|
617 |
* is performed by the scanner in the enclosing class. |
|
618 |
*/ |
|
619 |
private void reconfigurePipeline() { |
|
620 |
//fDTDValidator will be null in Stax mode |
|
621 |
if (fNamespaces && fDTDValidator == null) { |
|
622 |
fBindNamespaces = true; |
|
623 |
} |
|
624 |
else if (fNamespaces && !fDTDValidator.hasGrammar() ) { |
|
625 |
fBindNamespaces = true; |
|
626 |
fPerformValidation = fDTDValidator.validate(); |
|
627 |
// re-configure pipeline by removing DTDValidator |
|
628 |
XMLDocumentSource source = fDTDValidator.getDocumentSource(); |
|
629 |
XMLDocumentHandler handler = fDTDValidator.getDocumentHandler(); |
|
630 |
source.setDocumentHandler(handler); |
|
631 |
if (handler != null) |
|
632 |
handler.setDocumentSource(source); |
|
633 |
fDTDValidator.setDocumentSource(null); |
|
634 |
fDTDValidator.setDocumentHandler(null); |
|
635 |
} |
|
636 |
} // reconfigurePipeline() |
|
637 |
} |
|
638 |
||
639 |
} // class XMLNSDocumentScannerImpl |