60 |
import java.util.Locale; |
import java.util.Locale; |
61 |
import java.util.Stack; |
import java.util.Stack; |
62 |
|
|
|
// maintaining 1.1 compatibility for now ... more portable, PJava, etc |
|
|
// Iterator, Hashmap and ArrayList ought to be faster |
|
63 |
import java.util.ArrayList; |
import java.util.ArrayList; |
64 |
import java.util.Collections; |
import java.util.Collections; |
65 |
import java.util.Enumeration; |
import java.util.Enumeration; |
129 |
* @see org.xml.sax.Parser |
* @see org.xml.sax.Parser |
130 |
*/ |
*/ |
131 |
final public class SAXDriver |
final public class SAXDriver |
132 |
implements Locator, Attributes2, XMLReader, Parser, AttributeList |
implements Locator, Attributes2, XMLReader, Parser, AttributeList |
133 |
{ |
{ |
134 |
private final DefaultHandler2 base = new DefaultHandler2 (); |
|
135 |
private XmlParser parser; |
private final DefaultHandler2 base = new DefaultHandler2(); |
136 |
|
private XmlParser parser; |
137 |
private EntityResolver entityResolver = base; |
|
138 |
private EntityResolver2 resolver2 = null; |
private EntityResolver entityResolver = base; |
139 |
private ContentHandler contentHandler = base; |
private EntityResolver2 resolver2 = null; |
140 |
private DTDHandler dtdHandler = base; |
private ContentHandler contentHandler = base; |
141 |
private ErrorHandler errorHandler = base; |
private DTDHandler dtdHandler = base; |
142 |
private DeclHandler declHandler = base; |
private ErrorHandler errorHandler = base; |
143 |
private LexicalHandler lexicalHandler = base; |
private DeclHandler declHandler = base; |
144 |
|
private LexicalHandler lexicalHandler = base; |
145 |
private String elementName; |
|
146 |
private Stack entityStack; |
private String elementName; |
147 |
|
private Stack entityStack; |
148 |
// one vector (of object/struct): faster, smaller |
|
149 |
private List attributesList; |
// one vector (of object/struct): faster, smaller |
150 |
|
private List attributesList; |
151 |
private boolean namespaces = true; |
|
152 |
private boolean xmlNames = false; |
private boolean namespaces = true; |
153 |
private boolean extGE = true; |
private boolean xmlNames = false; |
154 |
private boolean extPE = true; |
private boolean extGE = true; |
155 |
private boolean resolveAll = true; |
private boolean extPE = true; |
156 |
private boolean useResolver2 = true; |
private boolean resolveAll = true; |
157 |
private boolean stringInterning = true; |
private boolean useResolver2 = true; |
158 |
|
|
159 |
private int attributeCount; |
// package private to allow (read-only) access in XmlParser |
160 |
private boolean attributes; |
boolean stringInterning = true; |
161 |
private String nsTemp []; |
|
162 |
private NamespaceSupport prefixStack; |
private int attributeCount; |
163 |
|
private boolean attributes; |
164 |
// |
private String[] nsTemp; |
165 |
// Constructor. |
private NamespaceSupport prefixStack; |
166 |
// |
|
167 |
|
// |
168 |
/** Constructs a SAX Parser. */ |
// Constructor. |
169 |
public SAXDriver () |
// |
170 |
{ |
|
171 |
reset (); |
/** |
172 |
} |
* Constructs a SAX Parser. |
173 |
|
*/ |
174 |
private void reset () |
public SAXDriver() |
175 |
{ |
{ |
176 |
elementName = null; |
reset(); |
177 |
entityStack = new Stack (); |
} |
|
attributesList = Collections.synchronizedList(new ArrayList()); |
|
|
attributeCount = 0; |
|
|
attributes = false; |
|
|
nsTemp = new String[3]; |
|
|
prefixStack = null; |
|
|
} |
|
178 |
|
|
179 |
|
private void reset() |
180 |
|
{ |
181 |
|
elementName = null; |
182 |
|
entityStack = new Stack(); |
183 |
|
attributesList = Collections.synchronizedList(new ArrayList()); |
184 |
|
attributeCount = 0; |
185 |
|
attributes = false; |
186 |
|
nsTemp = new String[3]; |
187 |
|
prefixStack = null; |
188 |
|
} |
189 |
|
|
|
// |
|
|
// Implementation of org.xml.sax.Parser. |
|
|
// |
|
190 |
|
|
191 |
/** |
// |
192 |
* <b>SAX1</b>: Sets the locale used for diagnostics; currently, |
// Implementation of org.xml.sax.Parser. |
193 |
* only locales using the English language are supported. |
// |
194 |
* @param locale The locale for which diagnostics will be generated |
|
195 |
*/ |
/** |
196 |
public void setLocale (Locale locale) |
* <b>SAX1</b>: Sets the locale used for diagnostics; currently, |
197 |
throws SAXException |
* only locales using the English language are supported. |
198 |
{ |
* @param locale The locale for which diagnostics will be generated |
199 |
if ("en".equals (locale.getLanguage ())) |
*/ |
200 |
return ; |
public void setLocale(Locale locale) |
201 |
|
throws SAXException |
202 |
throw new SAXException ("AElfred2 only supports English locales."); |
{ |
203 |
} |
if ("en".equals(locale.getLanguage())) |
204 |
|
{ |
205 |
|
return; |
206 |
|
} |
207 |
|
throw new SAXException ("AElfred2 only supports English locales."); |
208 |
|
} |
209 |
|
|
210 |
|
/** |
211 |
|
* <b>SAX2</b>: Returns the object used when resolving external |
212 |
|
* entities during parsing (both general and parameter entities). |
213 |
|
*/ |
214 |
|
public EntityResolver getEntityResolver() |
215 |
|
{ |
216 |
|
return (entityResolver == base) ? null : entityResolver; |
217 |
|
} |
218 |
|
|
219 |
/** |
/** |
220 |
* <b>SAX2</b>: Returns the object used when resolving external |
* <b>SAX1, SAX2</b>: Set the entity resolver for this parser. |
221 |
* entities during parsing (both general and parameter entities). |
* @param handler The object to receive entity events. |
222 |
*/ |
*/ |
223 |
public EntityResolver getEntityResolver () |
public void setEntityResolver(EntityResolver resolver) |
224 |
{ |
{ |
225 |
return (entityResolver == base) ? null : entityResolver; |
if (resolver instanceof EntityResolver2) |
226 |
} |
{ |
227 |
|
resolver2 = (EntityResolver2) resolver; |
228 |
|
} |
229 |
|
else |
230 |
|
{ |
231 |
|
resolver2 = null; |
232 |
|
} |
233 |
|
if (resolver == null) |
234 |
|
{ |
235 |
|
resolver = base; |
236 |
|
} |
237 |
|
entityResolver = resolver; |
238 |
|
} |
239 |
|
|
240 |
/** |
/** |
241 |
* <b>SAX1, SAX2</b>: Set the entity resolver for this parser. |
* <b>SAX2</b>: Returns the object used to process declarations related |
242 |
* @param handler The object to receive entity events. |
* to notations and unparsed entities. |
243 |
*/ |
*/ |
244 |
public void setEntityResolver (EntityResolver resolver) |
public DTDHandler getDTDHandler() |
245 |
{ |
{ |
246 |
if (resolver instanceof EntityResolver2) |
return (dtdHandler == base) ? null : dtdHandler; |
247 |
resolver2 = (EntityResolver2) resolver; |
} |
|
else |
|
|
resolver2 = null; |
|
|
if (resolver == null) |
|
|
resolver = base; |
|
|
entityResolver = resolver; |
|
|
} |
|
248 |
|
|
249 |
|
/** |
250 |
|
* <b>SAX1, SAX2</b>: Set the DTD handler for this parser. |
251 |
|
* @param handler The object to receive DTD events. |
252 |
|
*/ |
253 |
|
public void setDTDHandler(DTDHandler handler) |
254 |
|
{ |
255 |
|
if (handler == null) |
256 |
|
{ |
257 |
|
handler = base; |
258 |
|
} |
259 |
|
this.dtdHandler = handler; |
260 |
|
} |
261 |
|
|
|
/** |
|
|
* <b>SAX2</b>: Returns the object used to process declarations related |
|
|
* to notations and unparsed entities. |
|
|
*/ |
|
|
public DTDHandler getDTDHandler () |
|
|
{ |
|
|
return (dtdHandler == base) ? null : dtdHandler; |
|
|
} |
|
262 |
|
|
263 |
/** |
/** |
264 |
* <b>SAX1, SAX2</b>: Set the DTD handler for this parser. |
* <b>SAX1</b>: Set the document handler for this parser. If a |
265 |
* @param handler The object to receive DTD events. |
* content handler was set, this document handler will supplant it. |
266 |
*/ |
* The parser is set to report all XML 1.0 names rather than to |
267 |
public void setDTDHandler (DTDHandler handler) |
* filter out "xmlns" attributes (the "namespace-prefixes" feature |
268 |
{ |
* is set to true). |
269 |
if (handler == null) |
* |
270 |
handler = base; |
* @deprecated SAX2 programs should use the XMLReader interface |
271 |
this.dtdHandler = handler; |
* and a ContentHandler. |
272 |
} |
* |
273 |
|
* @param handler The object to receive document events. |
274 |
|
*/ |
275 |
|
public void setDocumentHandler(DocumentHandler handler) |
276 |
|
{ |
277 |
|
contentHandler = new Adapter(handler); |
278 |
|
xmlNames = true; |
279 |
|
} |
280 |
|
|
281 |
|
/** |
282 |
|
* <b>SAX2</b>: Returns the object used to report the logical |
283 |
|
* content of an XML document. |
284 |
|
*/ |
285 |
|
public ContentHandler getContentHandler() |
286 |
|
{ |
287 |
|
return (contentHandler == base) ? null : contentHandler; |
288 |
|
} |
289 |
|
|
290 |
/** |
/** |
291 |
* <b>SAX1</b>: Set the document handler for this parser. If a |
* <b>SAX2</b>: Assigns the object used to report the logical |
292 |
* content handler was set, this document handler will supplant it. |
* content of an XML document. If a document handler was set, |
293 |
* The parser is set to report all XML 1.0 names rather than to |
* this content handler will supplant it (but XML 1.0 style name |
294 |
* filter out "xmlns" attributes (the "namespace-prefixes" feature |
* reporting may remain enabled). |
295 |
* is set to true). |
*/ |
296 |
* |
public void setContentHandler(ContentHandler handler) |
297 |
* @deprecated SAX2 programs should use the XMLReader interface |
{ |
298 |
* and a ContentHandler. |
if (handler == null) |
299 |
* |
{ |
300 |
* @param handler The object to receive document events. |
handler = base; |
301 |
*/ |
} |
302 |
public void setDocumentHandler (DocumentHandler handler) |
contentHandler = handler; |
303 |
{ |
} |
|
contentHandler = new Adapter (handler); |
|
|
xmlNames = true; |
|
|
} |
|
304 |
|
|
305 |
/** |
/** |
306 |
* <b>SAX2</b>: Returns the object used to report the logical |
* <b>SAX1, SAX2</b>: Set the error handler for this parser. |
307 |
* content of an XML document. |
* @param handler The object to receive error events. |
308 |
*/ |
*/ |
309 |
public ContentHandler getContentHandler () |
public void setErrorHandler(ErrorHandler handler) |
310 |
{ |
{ |
311 |
return contentHandler == base ? null : contentHandler; |
if (handler == null) |
312 |
} |
{ |
313 |
|
handler = base; |
314 |
|
} |
315 |
|
this.errorHandler = handler; |
316 |
|
} |
317 |
|
|
318 |
/** |
/** |
319 |
* <b>SAX2</b>: Assigns the object used to report the logical |
* <b>SAX2</b>: Returns the object used to receive callbacks for XML |
320 |
* content of an XML document. If a document handler was set, |
* errors of all levels (fatal, nonfatal, warning); this is never null; |
321 |
* this content handler will supplant it (but XML 1.0 style name |
*/ |
322 |
* reporting may remain enabled). |
public ErrorHandler getErrorHandler() |
323 |
*/ |
{ |
324 |
public void setContentHandler (ContentHandler handler) |
return (errorHandler == base) ? null : errorHandler; |
325 |
{ |
} |
|
if (handler == null) |
|
|
handler = base; |
|
|
contentHandler = handler; |
|
|
} |
|
326 |
|
|
327 |
/** |
/** |
328 |
* <b>SAX1, SAX2</b>: Set the error handler for this parser. |
* <b>SAX1, SAX2</b>: Auxiliary API to parse an XML document, used mostly |
329 |
* @param handler The object to receive error events. |
* when no URI is available. |
330 |
*/ |
* If you want anything useful to happen, you should set |
331 |
public void setErrorHandler (ErrorHandler handler) |
* at least one type of handler. |
332 |
{ |
* @param source The XML input source. Don't set 'encoding' unless |
333 |
if (handler == null) |
* you know for a fact that it's correct. |
334 |
handler = base; |
* @see #setEntityResolver |
335 |
this.errorHandler = handler; |
* @see #setDTDHandler |
336 |
} |
* @see #setContentHandler |
337 |
|
* @see #setErrorHandler |
338 |
|
* @exception SAXException The handlers may throw any SAXException, |
339 |
|
* and the parser normally throws SAXParseException objects. |
340 |
|
* @exception IOException IOExceptions are normally through through |
341 |
|
* the parser if there are problems reading the source document. |
342 |
|
*/ |
343 |
|
public void parse(InputSource source) |
344 |
|
throws SAXException, IOException |
345 |
|
{ |
346 |
|
synchronized (base) |
347 |
|
{ |
348 |
|
parser = new XmlParser(); |
349 |
|
if (namespaces) |
350 |
|
{ |
351 |
|
prefixStack = new NamespaceSupport(); |
352 |
|
} |
353 |
|
else if (!xmlNames) |
354 |
|
{ |
355 |
|
throw new IllegalStateException(); |
356 |
|
} |
357 |
|
parser.setHandler(this); |
358 |
|
|
359 |
|
try |
360 |
|
{ |
361 |
|
Reader r = source.getCharacterStream(); |
362 |
|
InputStream in = source.getByteStream(); |
363 |
|
|
364 |
|
parser.doParse(source.getSystemId(), |
365 |
|
source.getPublicId(), |
366 |
|
r, |
367 |
|
in, |
368 |
|
source.getEncoding()); |
369 |
|
} |
370 |
|
catch (SAXException e) |
371 |
|
{ |
372 |
|
throw e; |
373 |
|
} |
374 |
|
catch (IOException e) |
375 |
|
{ |
376 |
|
throw e; |
377 |
|
} |
378 |
|
catch (RuntimeException e) |
379 |
|
{ |
380 |
|
throw e; |
381 |
|
} |
382 |
|
catch (Exception e) |
383 |
|
{ |
384 |
|
throw new SAXParseException(e.getMessage(), this, e); |
385 |
|
} |
386 |
|
finally |
387 |
|
{ |
388 |
|
contentHandler.endDocument(); |
389 |
|
reset(); |
390 |
|
} |
391 |
|
} |
392 |
|
} |
393 |
|
|
394 |
/** |
/** |
395 |
* <b>SAX2</b>: Returns the object used to receive callbacks for XML |
* <b>SAX1, SAX2</b>: Preferred API to parse an XML document, using a |
396 |
* errors of all levels (fatal, nonfatal, warning); this is never null; |
* system identifier (URI). |
397 |
*/ |
*/ |
398 |
public ErrorHandler getErrorHandler () |
public void parse(String systemId) |
399 |
{ return errorHandler == base ? null : errorHandler; } |
throws SAXException, IOException |
400 |
|
{ |
401 |
|
parse(new InputSource(systemId)); |
402 |
|
} |
403 |
|
|
404 |
|
// |
405 |
|
// Implementation of SAX2 "XMLReader" interface |
406 |
|
// |
407 |
|
static final String FEATURE = "http://xml.org/sax/features/"; |
408 |
|
static final String PROPERTY = "http://xml.org/sax/properties/"; |
409 |
|
|
410 |
|
/** |
411 |
|
* <b>SAX2</b>: Tells the value of the specified feature flag. |
412 |
|
* |
413 |
|
* @exception SAXNotRecognizedException thrown if the feature flag |
414 |
|
* is neither built in, nor yet assigned. |
415 |
|
*/ |
416 |
|
public boolean getFeature(String featureId) |
417 |
|
throws SAXNotRecognizedException, SAXNotSupportedException |
418 |
|
{ |
419 |
|
if ((FEATURE + "validation").equals(featureId)) |
420 |
|
{ |
421 |
|
return false; |
422 |
|
} |
423 |
|
|
424 |
/** |
// external entities (both types) are optionally included |
425 |
* <b>SAX1, SAX2</b>: Auxiliary API to parse an XML document, used mostly |
if ((FEATURE + "external-general-entities").equals(featureId)) |
426 |
* when no URI is available. |
{ |
427 |
* If you want anything useful to happen, you should set |
return extGE; |
428 |
* at least one type of handler. |
} |
429 |
* @param source The XML input source. Don't set 'encoding' unless |
if ((FEATURE + "external-parameter-entities").equals(featureId)) |
430 |
* you know for a fact that it's correct. |
{ |
431 |
* @see #setEntityResolver |
return extPE; |
432 |
* @see #setDTDHandler |
} |
433 |
* @see #setContentHandler |
|
434 |
* @see #setErrorHandler |
// element/attribute names are as written in document; no mangling |
435 |
* @exception SAXException The handlers may throw any SAXException, |
if ((FEATURE + "namespace-prefixes").equals(featureId)) |
436 |
* and the parser normally throws SAXParseException objects. |
{ |
437 |
* @exception IOException IOExceptions are normally through through |
return xmlNames; |
438 |
* the parser if there are problems reading the source document. |
} |
|
*/ |
|
|
public void parse (InputSource source) |
|
|
throws SAXException, IOException |
|
|
{ |
|
|
synchronized (base) { |
|
|
parser = new XmlParser (); |
|
|
if (namespaces) |
|
|
prefixStack = new NamespaceSupport (); |
|
|
else if (!xmlNames) |
|
|
throw new IllegalStateException (); |
|
|
parser.setHandler (this); |
|
|
|
|
|
try { |
|
|
|
|
|
Reader r = source.getCharacterStream(); |
|
|
InputStream in = source.getByteStream(); |
|
|
|
|
|
|
|
|
parser.doParse (source.getSystemId (), |
|
|
source.getPublicId (), |
|
|
r, |
|
|
in, |
|
|
source.getEncoding ()); |
|
|
} catch (SAXException e) { |
|
|
throw e; |
|
|
} catch (IOException e) { |
|
|
throw e; |
|
|
} catch (RuntimeException e) { |
|
|
throw e; |
|
|
} catch (Exception e) { |
|
|
throw new SAXParseException (e.getMessage (), this, e); |
|
|
} finally { |
|
|
contentHandler.endDocument (); |
|
|
reset(); |
|
|
} |
|
|
} |
|
|
} |
|
439 |
|
|
440 |
|
// report element/attribute namespaces? |
441 |
|
if ((FEATURE + "namespaces").equals(featureId)) |
442 |
|
{ |
443 |
|
return namespaces; |
444 |
|
} |
445 |
|
|
446 |
/** |
// all PEs and GEs are reported |
447 |
* <b>SAX1, SAX2</b>: Preferred API to parse an XML document, using a |
if ((FEATURE + "lexical-handler/parameter-entities").equals(featureId)) |
448 |
* system identifier (URI). |
{ |
449 |
*/ |
return true; |
450 |
public void parse (String systemId) |
} |
|
throws SAXException, IOException |
|
|
{ |
|
|
parse (new InputSource (systemId)); |
|
|
} |
|
451 |
|
|
452 |
// |
// default is true |
453 |
// Implementation of SAX2 "XMLReader" interface |
if ((FEATURE + "string-interning").equals(featureId)) |
454 |
// |
{ |
455 |
static final String FEATURE = "http://xml.org/sax/features/"; |
return stringInterning; |
456 |
static final String PROPERTY = "http://xml.org/sax/properties/"; |
} |
457 |
|
|
458 |
|
// EXTENSIONS 1.1 |
459 |
|
|
460 |
|
// always returns isSpecified info |
461 |
|
if ((FEATURE + "use-attributes2").equals(featureId)) |
462 |
|
{ |
463 |
|
return true; |
464 |
|
} |
465 |
|
|
466 |
|
// meaningful between startDocument/endDocument |
467 |
|
if ((FEATURE + "is-standalone").equals(featureId)) |
468 |
|
{ |
469 |
|
if (parser == null) |
470 |
|
{ |
471 |
|
throw new SAXNotSupportedException(featureId); |
472 |
|
} |
473 |
|
return parser.isStandalone(); |
474 |
|
} |
475 |
|
|
476 |
/** |
// optionally don't absolutize URIs in declarations |
477 |
* <b>SAX2</b>: Tells the value of the specified feature flag. |
if ((FEATURE + "resolve-dtd-uris").equals(featureId)) |
478 |
* |
{ |
479 |
* @exception SAXNotRecognizedException thrown if the feature flag |
return resolveAll; |
480 |
* is neither built in, nor yet assigned. |
} |
|
*/ |
|
|
public boolean getFeature (String featureId) |
|
|
throws SAXNotRecognizedException, SAXNotSupportedException |
|
|
{ |
|
|
if ((FEATURE + "validation").equals (featureId)) |
|
|
return false; |
|
481 |
|
|
482 |
// external entities (both types) are optionally included |
// optionally use resolver2 interface methods, if possible |
483 |
if ((FEATURE + "external-general-entities").equals (featureId)) |
if ((FEATURE + "use-entity-resolver2").equals(featureId)) |
484 |
return extGE; |
{ |
485 |
if ((FEATURE + "external-parameter-entities") .equals (featureId)) |
return useResolver2; |
486 |
return extPE; |
} |
487 |
|
|
488 |
// element/attribute names are as written in document; no mangling |
throw new SAXNotRecognizedException(featureId); |
489 |
if ((FEATURE + "namespace-prefixes").equals (featureId)) |
} |
|
return xmlNames; |
|
|
|
|
|
// report element/attribute namespaces? |
|
|
if ((FEATURE + "namespaces").equals (featureId)) |
|
|
return namespaces; |
|
|
|
|
|
// all PEs and GEs are reported |
|
|
if ((FEATURE + "lexical-handler/parameter-entities").equals (featureId)) |
|
|
return true; |
|
|
|
|
|
// default is true |
|
|
if ((FEATURE + "string-interning").equals (featureId)) |
|
|
return stringInterning; |
|
|
|
|
|
// EXTENSIONS 1.1 |
|
|
|
|
|
// always returns isSpecified info |
|
|
if ((FEATURE + "use-attributes2").equals (featureId)) |
|
|
return true; |
|
|
|
|
|
// meaningful between startDocument/endDocument |
|
|
if ((FEATURE + "is-standalone").equals (featureId)) { |
|
|
if (parser == null) |
|
|
throw new SAXNotSupportedException (featureId); |
|
|
return parser.isStandalone (); |
|
|
} |
|
|
|
|
|
// optionally don't absolutize URIs in declarations |
|
|
if ((FEATURE + "resolve-dtd-uris").equals (featureId)) |
|
|
return resolveAll; |
|
|
|
|
|
// optionally use resolver2 interface methods, if possible |
|
|
if ((FEATURE + "use-entity-resolver2").equals (featureId)) |
|
|
return useResolver2; |
|
|
|
|
|
throw new SAXNotRecognizedException (featureId); |
|
|
} |
|
490 |
|
|
491 |
// package private |
// package private |
492 |
DeclHandler getDeclHandler () { return declHandler; } |
DeclHandler getDeclHandler() |
493 |
|
{ |
494 |
|
return declHandler; |
495 |
|
} |
496 |
|
|
497 |
// package private |
// package private |
498 |
boolean resolveURIs () { return resolveAll; } |
boolean resolveURIs() |
499 |
|
{ |
500 |
|
return resolveAll; |
501 |
|
} |
502 |
|
|
503 |
/** |
/** |
504 |
* <b>SAX2</b>: Returns the specified property. |
* <b>SAX2</b>: Returns the specified property. |
505 |
* |
* |
506 |
* @exception SAXNotRecognizedException thrown if the property value |
* @exception SAXNotRecognizedException thrown if the property value |
507 |
* is neither built in, nor yet stored. |
* is neither built in, nor yet stored. |
508 |
*/ |
*/ |
509 |
public Object getProperty (String propertyId) |
public Object getProperty(String propertyId) |
510 |
throws SAXNotRecognizedException |
throws SAXNotRecognizedException |
511 |
{ |
{ |
512 |
if ((PROPERTY + "declaration-handler").equals (propertyId)) |
if ((PROPERTY + "declaration-handler").equals(propertyId)) |
513 |
return declHandler == base ? null : declHandler; |
{ |
514 |
|
return (declHandler == base) ? null : declHandler; |
515 |
|
} |
516 |
|
|
517 |
if ((PROPERTY + "lexical-handler").equals (propertyId)) |
if ((PROPERTY + "lexical-handler").equals(propertyId)) |
518 |
return lexicalHandler == base ? null : lexicalHandler; |
{ |
519 |
|
return (lexicalHandler == base) ? null : lexicalHandler; |
520 |
// unknown properties |
} |
521 |
throw new SAXNotRecognizedException (propertyId); |
|
522 |
} |
// unknown properties |
523 |
|
throw new SAXNotRecognizedException(propertyId); |
524 |
|
} |
525 |
|
|
526 |
/** |
/** |
527 |
* <b>SAX2</b>: Sets the state of feature flags in this parser. Some |
* <b>SAX2</b>: Sets the state of feature flags in this parser. Some |
528 |
* built-in feature flags are mutable. |
* built-in feature flags are mutable. |
529 |
*/ |
*/ |
530 |
public void setFeature (String featureId, boolean value) |
public void setFeature(String featureId, boolean value) |
531 |
throws SAXNotRecognizedException, SAXNotSupportedException |
throws SAXNotRecognizedException, SAXNotSupportedException |
532 |
{ |
{ |
533 |
boolean state; |
boolean state; |
534 |
|
|
535 |
// Features with a defined value, we just change it if we can. |
// Features with a defined value, we just change it if we can. |
536 |
state = getFeature (featureId); |
state = getFeature (featureId); |
537 |
|
|
538 |
if (state == value) |
if (state == value) |
539 |
return; |
{ |
540 |
if (parser != null) |
return; |
541 |
throw new SAXNotSupportedException ("not while parsing"); |
} |
542 |
|
if (parser != null) |
543 |
if ((FEATURE + "namespace-prefixes").equals (featureId)) { |
{ |
544 |
// in this implementation, this only affects xmlns reporting |
throw new SAXNotSupportedException("not while parsing"); |
545 |
xmlNames = value; |
} |
|
// forcibly prevent illegal parser state |
|
|
if (!xmlNames) |
|
|
namespaces = true; |
|
|
return; |
|
|
} |
|
|
|
|
|
if ((FEATURE + "namespaces").equals (featureId)) { |
|
|
namespaces = value; |
|
|
// forcibly prevent illegal parser state |
|
|
if (!namespaces) |
|
|
xmlNames = true; |
|
|
return; |
|
|
} |
|
|
|
|
|
if ((FEATURE + "external-general-entities").equals (featureId)) { |
|
|
extGE = value; |
|
|
return; |
|
|
} |
|
|
if ((FEATURE + "external-parameter-entities") .equals (featureId)) { |
|
|
extPE = value; |
|
|
return; |
|
|
} |
|
|
if ((FEATURE + "resolve-dtd-uris").equals (featureId)) { |
|
|
resolveAll = value; |
|
|
return; |
|
|
} |
|
|
|
|
|
if ((FEATURE + "use-entity-resolver2").equals (featureId)) { |
|
|
useResolver2 = value; |
|
|
return; |
|
|
} |
|
|
|
|
|
throw new SAXNotRecognizedException (featureId); |
|
|
} |
|
546 |
|
|
547 |
/** |
if ((FEATURE + "namespace-prefixes").equals(featureId)) |
548 |
* <b>SAX2</b>: Assigns the specified property. Like SAX1 handlers, |
{ |
549 |
* these may be changed at any time. |
// in this implementation, this only affects xmlns reporting |
550 |
*/ |
xmlNames = value; |
551 |
public void setProperty (String propertyId, Object value) |
// forcibly prevent illegal parser state |
552 |
throws SAXNotRecognizedException, SAXNotSupportedException |
if (!xmlNames) |
553 |
{ |
{ |
554 |
// see if the property is recognized |
namespaces = true; |
555 |
getProperty (propertyId); |
} |
556 |
|
return; |
557 |
|
} |
558 |
|
|
559 |
// Properties with a defined value, we just change it if we can. |
if ((FEATURE + "namespaces").equals(featureId)) |
560 |
|
{ |
561 |
|
namespaces = value; |
562 |
|
// forcibly prevent illegal parser state |
563 |
|
if (!namespaces) |
564 |
|
{ |
565 |
|
xmlNames = true; |
566 |
|
} |
567 |
|
return; |
568 |
|
} |
569 |
|
|
570 |
if ((PROPERTY + "declaration-handler").equals (propertyId)) { |
if ((FEATURE + "external-general-entities").equals(featureId)) |
571 |
if (value == null) |
{ |
572 |
declHandler = base; |
extGE = value; |
573 |
else if (! (value instanceof DeclHandler)) |
return; |
574 |
throw new SAXNotSupportedException (propertyId); |
} |
575 |
else |
if ((FEATURE + "external-parameter-entities").equals(featureId)) |
576 |
declHandler = (DeclHandler) value; |
{ |
577 |
return ; |
extPE = value; |
578 |
} |
return; |
579 |
|
} |
580 |
if ((PROPERTY + "lexical-handler").equals (propertyId)) { |
if ((FEATURE + "resolve-dtd-uris").equals(featureId)) |
581 |
if (value == null) |
{ |
582 |
lexicalHandler = base; |
resolveAll = value; |
583 |
else if (! (value instanceof LexicalHandler)) |
return; |
584 |
throw new SAXNotSupportedException (propertyId); |
} |
|
else |
|
|
lexicalHandler = (LexicalHandler) value; |
|
|
return ; |
|
|
} |
|
585 |
|
|
586 |
throw new SAXNotSupportedException (propertyId); |
if ((FEATURE + "use-entity-resolver2").equals(featureId)) |
587 |
} |
{ |
588 |
|
useResolver2 = value; |
589 |
|
return; |
590 |
|
} |
591 |
|
|
592 |
|
throw new SAXNotRecognizedException(featureId); |
593 |
|
} |
594 |
|
|
595 |
// |
/** |
596 |
// This is where the driver receives XmlParser callbacks and translates |
* <b>SAX2</b>: Assigns the specified property. Like SAX1 handlers, |
597 |
// them into SAX callbacks. Some more callbacks have been added for |
* these may be changed at any time. |
598 |
// SAX2 support. |
*/ |
599 |
// |
public void setProperty(String propertyId, Object value) |
600 |
|
throws SAXNotRecognizedException, SAXNotSupportedException |
601 |
|
{ |
602 |
|
// see if the property is recognized |
603 |
|
getProperty(propertyId); |
604 |
|
|
605 |
|
// Properties with a defined value, we just change it if we can. |
606 |
|
|
607 |
|
if ((PROPERTY + "declaration-handler").equals(propertyId)) |
608 |
|
{ |
609 |
|
if (value == null) |
610 |
|
{ |
611 |
|
declHandler = base; |
612 |
|
} |
613 |
|
else if (!(value instanceof DeclHandler)) |
614 |
|
{ |
615 |
|
throw new SAXNotSupportedException(propertyId); |
616 |
|
} |
617 |
|
else |
618 |
|
{ |
619 |
|
declHandler = (DeclHandler) value; |
620 |
|
} |
621 |
|
return ; |
622 |
|
} |
623 |
|
|
624 |
|
if ((PROPERTY + "lexical-handler").equals(propertyId)) |
625 |
|
{ |
626 |
|
if (value == null) |
627 |
|
{ |
628 |
|
lexicalHandler = base; |
629 |
|
} |
630 |
|
else if (!(value instanceof LexicalHandler)) |
631 |
|
{ |
632 |
|
throw new SAXNotSupportedException(propertyId); |
633 |
|
} |
634 |
|
else |
635 |
|
{ |
636 |
|
lexicalHandler = (LexicalHandler) value; |
637 |
|
} |
638 |
|
return; |
639 |
|
} |
640 |
|
|
641 |
|
throw new SAXNotSupportedException(propertyId); |
642 |
|
} |
643 |
|
|
644 |
void startDocument () |
// |
645 |
throws SAXException |
// This is where the driver receives XmlParser callbacks and translates |
646 |
{ |
// them into SAX callbacks. Some more callbacks have been added for |
647 |
contentHandler.setDocumentLocator (this); |
// SAX2 support. |
648 |
contentHandler.startDocument (); |
// |
649 |
attributesList.clear (); |
|
650 |
} |
void startDocument() |
651 |
|
throws SAXException |
652 |
|
{ |
653 |
|
contentHandler.setDocumentLocator(this); |
654 |
|
contentHandler.startDocument(); |
655 |
|
attributesList.clear(); |
656 |
|
} |
657 |
|
|
658 |
void xmlDecl(String version, |
void xmlDecl(String version, |
659 |
String encoding, |
String encoding, |
660 |
boolean standalone, |
boolean standalone, |
661 |
String inputEncoding) |
String inputEncoding) |
662 |
throws SAXException |
throws SAXException |
663 |
{ |
{ |
664 |
if (contentHandler instanceof ContentHandler2) |
if (contentHandler instanceof ContentHandler2) |
665 |
{ |
{ |
666 |
((ContentHandler2) contentHandler).xmlDecl(version, |
((ContentHandler2) contentHandler).xmlDecl(version, |
667 |
encoding, |
encoding, |
668 |
standalone, |
standalone, |
669 |
inputEncoding); |
inputEncoding); |
670 |
} |
} |
671 |
} |
} |
672 |
|
|
673 |
void skippedEntity (String name) |
void skippedEntity(String name) |
674 |
throws SAXException |
throws SAXException |
675 |
{ contentHandler.skippedEntity (name); } |
{ |
676 |
|
contentHandler.skippedEntity(name); |
677 |
|
} |
678 |
|
|
679 |
InputSource getExternalSubset (String name, String baseURI) |
InputSource getExternalSubset(String name, String baseURI) |
680 |
throws SAXException, IOException |
throws SAXException, IOException |
681 |
{ |
{ |
682 |
if (resolver2 == null || !useResolver2 || !extPE) |
if (resolver2 == null || !useResolver2 || !extPE) |
683 |
return null; |
{ |
684 |
return resolver2.getExternalSubset (name, baseURI); |
return null; |
685 |
} |
} |
686 |
|
return resolver2.getExternalSubset(name, baseURI); |
687 |
|
} |
688 |
|
|
689 |
InputSource resolveEntity (boolean isPE, String name, |
InputSource resolveEntity(boolean isPE, String name, |
690 |
InputSource in, String baseURI) |
InputSource in, String baseURI) |
691 |
throws SAXException, IOException |
throws SAXException, IOException |
692 |
{ |
{ |
693 |
InputSource source; |
InputSource source; |
694 |
|
|
695 |
|
// external entities might be skipped |
696 |
|
if (isPE && !extPE) |
697 |
|
{ |
698 |
|
return null; |
699 |
|
} |
700 |
|
if (!isPE && !extGE) |
701 |
|
{ |
702 |
|
return null; |
703 |
|
} |
704 |
|
|
705 |
// external entities might be skipped |
// ... or not |
706 |
if (isPE && !extPE) |
lexicalHandler.startEntity(name); |
707 |
return null; |
if (resolver2 != null && useResolver2) |
708 |
if (!isPE && !extGE) |
{ |
709 |
return null; |
source = resolver2.resolveEntity(name, in.getPublicId(), |
710 |
|
baseURI, in.getSystemId()); |
711 |
// ... or not |
if (source == null) |
712 |
lexicalHandler.startEntity (name); |
{ |
713 |
if (resolver2 != null && useResolver2) { |
in.setSystemId(absolutize(baseURI, |
714 |
source = resolver2.resolveEntity (name, in.getPublicId (), |
in.getSystemId(), false)); |
715 |
baseURI, in.getSystemId ()); |
source = in; |
716 |
if (source == null) { |
} |
717 |
in.setSystemId (absolutize (baseURI, |
} |
718 |
in.getSystemId (), false)); |
else |
719 |
source = in; |
{ |
720 |
} |
in.setSystemId(absolutize(baseURI, in.getSystemId(), false)); |
721 |
} else { |
source = entityResolver.resolveEntity(in.getPublicId(), |
722 |
in.setSystemId (absolutize (baseURI, in.getSystemId (), false)); |
in.getSystemId()); |
723 |
source = entityResolver.resolveEntity (in.getPublicId (), |
if (source == null) |
724 |
in.getSystemId ()); |
{ |
725 |
if (source == null) |
source = in; |
726 |
source = in; |
} |
727 |
} |
} |
728 |
startExternalEntity (name, source.getSystemId (), true); |
startExternalEntity(name, source.getSystemId(), true); |
729 |
return source; |
return source; |
730 |
} |
} |
731 |
|
|
732 |
// absolutize a system ID relative to the specified base URI |
// absolutize a system ID relative to the specified base URI |
733 |
// (temporarily) package-visible for external entity decls |
// (temporarily) package-visible for external entity decls |
734 |
String absolutize (String baseURI, String systemId, boolean nice) |
String absolutize(String baseURI, String systemId, boolean nice) |
735 |
throws MalformedURLException, SAXException |
throws MalformedURLException, SAXException |
736 |
{ |
{ |
737 |
// FIXME normalize system IDs -- when? |
// FIXME normalize system IDs -- when? |
738 |
// - Convert to UTF-8 |
// - Convert to UTF-8 |
739 |
// - Map reserved and non-ASCII characters to %HH |
// - Map reserved and non-ASCII characters to %HH |
740 |
|
|
741 |
try { |
try |
742 |
if (baseURI == null) { |
{ |
743 |
warn ("No base URI; hope this SYSTEM id is absolute: " |
if (baseURI == null && XmlParser.uriWarnings) |
744 |
+ systemId); |
{ |
745 |
return new URL (systemId).toString (); |
warn ("No base URI; hope this SYSTEM id is absolute: " |
746 |
} else |
+ systemId); |
747 |
return new URL (new URL (baseURI), systemId).toString (); |
return new URL(systemId).toString(); |
748 |
|
} |
749 |
} catch (MalformedURLException e) { |
else |
750 |
|
{ |
751 |
// Let unknown URI schemes pass through unless we need |
return new URL(new URL(baseURI), systemId).toString(); |
752 |
// the JVM to map them to i/o streams for us... |
} |
753 |
if (!nice) |
} |
754 |
throw e; |
catch (MalformedURLException e) |
755 |
|
{ |
756 |
// sometimes sysids for notations or unparsed entities |
// Let unknown URI schemes pass through unless we need |
757 |
// aren't really URIs... |
// the JVM to map them to i/o streams for us... |
758 |
warn ("Can't absolutize SYSTEM id: " + e.getMessage ()); |
if (!nice) |
759 |
return systemId; |
{ |
760 |
} |
throw e; |
761 |
} |
} |
762 |
|
|
763 |
|
// sometimes sysids for notations or unparsed entities |
764 |
|
// aren't really URIs... |
765 |
|
warn("Can't absolutize SYSTEM id: " + e.getMessage()); |
766 |
|
return systemId; |
767 |
|
} |
768 |
|
} |
769 |
|
|
770 |
void startExternalEntity (String name, String systemId, |
void startExternalEntity(String name, String systemId, boolean stackOnly) |
|
boolean stackOnly) |
|
771 |
throws SAXException |
throws SAXException |
772 |
{ |
{ |
773 |
// The following warning was deleted because the application has the |
// The following warning was deleted because the application has the |
774 |
// option of not setting systemId. Sun's JAXP or Xerces seems to |
// option of not setting systemId. Sun's JAXP or Xerces seems to |
775 |
// ignore this case. |
// ignore this case. |
776 |
/* |
/* |
777 |
if (systemId == null) |
if (systemId == null) |
778 |
warn ("URI was not reported to parser for entity " + name); |
warn ("URI was not reported to parser for entity " + name); |
779 |
*/ |
*/ |
780 |
if (!stackOnly) // spliced [dtd] needs startEntity |
if (!stackOnly) // spliced [dtd] needs startEntity |
781 |
lexicalHandler.startEntity (name); |
{ |
782 |
entityStack.push (systemId); |
lexicalHandler.startEntity(name); |
783 |
} |
} |
784 |
|
entityStack.push(systemId); |
785 |
|
} |
786 |
|
|
787 |
void endExternalEntity (String name) |
void endExternalEntity(String name) |
788 |
throws SAXException |
throws SAXException |
789 |
{ |
{ |
790 |
if (!"[document]".equals (name)) |
if (!"[document]".equals(name)) |
791 |
lexicalHandler.endEntity (name); |
{ |
792 |
entityStack.pop (); |
lexicalHandler.endEntity(name); |
793 |
} |
} |
794 |
|
entityStack.pop(); |
795 |
|
} |
796 |
|
|
797 |
void startInternalEntity (String name) |
void startInternalEntity(String name) |
798 |
throws SAXException |
throws SAXException |
799 |
{ |
{ |
800 |
lexicalHandler.startEntity (name); |
lexicalHandler.startEntity(name); |
801 |
} |
} |
802 |
|
|
803 |
void endInternalEntity (String name) |
void endInternalEntity(String name) |
804 |
throws SAXException |
throws SAXException |
805 |
{ |
{ |
806 |
lexicalHandler.endEntity (name); |
lexicalHandler.endEntity(name); |
807 |
} |
} |
808 |
|
|
809 |
void doctypeDecl (String name, String publicId, String systemId) |
void doctypeDecl(String name, String publicId, String systemId) |
810 |
throws SAXException |
throws SAXException |
811 |
{ |
{ |
812 |
lexicalHandler.startDTD (name, publicId, systemId); |
lexicalHandler.startDTD(name, publicId, systemId); |
813 |
|
|
814 |
// ... the "name" is a declaration and should be given |
// ... the "name" is a declaration and should be given |
815 |
// to the DeclHandler (but sax2 doesn't). |
// to the DeclHandler (but sax2 doesn't). |
816 |
|
|
817 |
// the IDs for the external subset are lexical details, |
// the IDs for the external subset are lexical details, |
818 |
// as are the contents of the internal subset; but sax2 |
// as are the contents of the internal subset; but sax2 |
819 |
// doesn't provide the internal subset "pre-parse" |
// doesn't provide the internal subset "pre-parse" |
820 |
} |
} |
821 |
|
|
822 |
|
void notationDecl(String name, String publicId, String systemId, |
823 |
|
String baseUri) |
824 |
|
throws SAXException |
825 |
|
{ |
826 |
|
try |
827 |
|
{ |
828 |
|
dtdHandler.notationDecl(name, publicId, |
829 |
|
(resolveAll && systemId != null) |
830 |
|
? absolutize(baseUri, systemId, true) |
831 |
|
: systemId); |
832 |
|
} |
833 |
|
catch (IOException e) |
834 |
|
{ |
835 |
|
// "can't happen" |
836 |
|
throw new SAXParseException(e.getMessage(), this, e); |
837 |
|
} |
838 |
|
} |
839 |
|
|
840 |
void notationDecl (String name, String ids []) |
void unparsedEntityDecl(String name, String publicId, String systemId, |
841 |
|
String baseUri, String notation) |
842 |
throws SAXException |
throws SAXException |
843 |
{ |
{ |
844 |
try { |
try |
845 |
dtdHandler.notationDecl (name, ids [0], |
{ |
846 |
(resolveAll && ids [1] != null) |
dtdHandler.unparsedEntityDecl(name, publicId, |
847 |
? absolutize (ids [2], ids [1], true) |
resolveAll |
848 |
: ids [1]); |
? absolutize(baseUri, systemId, true) |
849 |
} catch (IOException e) { |
: systemId, |
850 |
// "can't happen" |
notation); |
851 |
throw new SAXParseException (e.getMessage (), this, e); |
} |
852 |
} |
catch (IOException e) |
853 |
} |
{ |
854 |
|
// "can't happen" |
855 |
|
throw new SAXParseException(e.getMessage(), this, e); |
856 |
|
} |
857 |
|
} |
858 |
|
|
859 |
void unparsedEntityDecl (String name, String ids [], String notation) |
void endDoctype() |
860 |
throws SAXException |
throws SAXException |
861 |
{ |
{ |
862 |
try { |
lexicalHandler.endDTD(); |
863 |
dtdHandler.unparsedEntityDecl (name, ids [0], |
} |
|
resolveAll |
|
|
? absolutize (ids [2], ids [1], true) |
|
|
: ids [1], |
|
|
notation); |
|
|
} catch (IOException e) { |
|
|
// "can't happen" |
|
|
throw new SAXParseException (e.getMessage (), this, e); |
|
|
} |
|
|
} |
|
864 |
|
|
865 |
void endDoctype () |
private void declarePrefix(String prefix, String uri) |
866 |
throws SAXException |
throws SAXException |
867 |
{ |
{ |
868 |
lexicalHandler.endDTD (); |
int index = uri.indexOf(':'); |
|
} |
|
869 |
|
|
870 |
private void declarePrefix (String prefix, String uri) |
// many versions of nwalsh docbook stylesheets |
871 |
throws SAXException |
// have bogus URLs; so this can't be an error... |
872 |
{ |
if (index < 1 && uri.length() != 0) |
873 |
int index = uri.indexOf (':'); |
{ |
874 |
|
warn("relative URI for namespace: " + uri); |
875 |
|
} |
876 |
|
|
877 |
// many versions of nwalsh docbook stylesheets |
// FIXME: char [0] must be ascii alpha; chars [1..index] |
878 |
// have bogus URLs; so this can't be an error... |
// must be ascii alphanumeric or in "+-." [RFC 2396] |
879 |
if (index < 1 && uri.length () != 0) |
|
880 |
warn ("relative URI for namespace: " + uri); |
//Namespace Constraints |
881 |
|
//name for xml prefix must be http://www.w3.org/XML/1998/namespace |
882 |
// FIXME: char [0] must be ascii alpha; chars [1..index] |
boolean prefixEquality = prefix.equals("xml"); |
883 |
// must be ascii alphanumeric or in "+-." [RFC 2396] |
boolean uriEquality = uri.equals("http://www.w3.org/XML/1998/namespace"); |
884 |
|
if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality)) |
885 |
//Namespace Constraints |
{ |
886 |
//name for xml prefix must be http://www.w3.org/XML/1998/namespace |
fatal("xml is by definition bound to the namespace name " + |
887 |
boolean prefixEquality = prefix.equals("xml"); |
"http://www.w3.org/XML/1998/namespace"); |
888 |
boolean uriEquality = uri.equals("http://www.w3.org/XML/1998/namespace"); |
} |
889 |
if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality)) |
|
890 |
fatal ("xml is by definition bound to the namespace name " + |
//xmlns prefix declaration is illegal but xml prefix declaration is llegal... |
891 |
"http://www.w3.org/XML/1998/namespace"); |
if (prefixEquality && uriEquality) |
892 |
|
{ |
893 |
//xmlns prefix declaration is illegal but xml prefix declaration is llegal... |
return; |
894 |
if (prefixEquality && uriEquality) |
} |
895 |
return; |
|
896 |
|
//name for xmlns prefix must be http://www.w3.org/2000/xmlns/ |
897 |
//name for xmlns prefix must be http://www.w3.org/2000/xmlns/ |
prefixEquality = prefix.equals("xmlns"); |
898 |
prefixEquality = prefix.equals("xmlns"); |
uriEquality = uri.equals("http://www.w3.org/2000/xmlns/"); |
899 |
uriEquality = uri.equals("http://www.w3.org/2000/xmlns/"); |
if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality)) |
900 |
if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality)) |
{ |
901 |
fatal("http://www.w3.org/2000/xmlns/ is by definition bound" + |
fatal("http://www.w3.org/2000/xmlns/ is by definition bound" + |
902 |
" to prefix xmlns"); |
" to prefix xmlns"); |
903 |
|
} |
904 |
//even if the uri is http://www.w3.org/2000/xmlns/ it is illegal to declare it |
|
905 |
if (prefixEquality && uriEquality) |
//even if the uri is http://www.w3.org/2000/xmlns/ |
906 |
fatal ("declaring the xmlns prefix is illegal"); |
// it is illegal to declare it |
907 |
|
if (prefixEquality && uriEquality) |
908 |
uri = uri.intern (); |
{ |
909 |
prefixStack.declarePrefix (prefix, uri); |
fatal ("declaring the xmlns prefix is illegal"); |
910 |
contentHandler.startPrefixMapping (prefix, uri); |
} |
911 |
} |
|
912 |
|
uri = uri.intern(); |
913 |
|
prefixStack.declarePrefix(prefix, uri); |
914 |
|
contentHandler.startPrefixMapping(prefix, uri); |
915 |
|
} |
916 |
|
|
917 |
void attribute (String qname, String value, boolean isSpecified) |
void attribute(String qname, String value, boolean isSpecified) |
918 |
throws SAXException |
throws SAXException |
919 |
{ |
{ |
920 |
if (!attributes) { |
if (!attributes) |
921 |
attributes = true; |
{ |
922 |
if (namespaces) |
attributes = true; |
923 |
prefixStack.pushContext (); |
if (namespaces) |
924 |
} |
{ |
925 |
|
prefixStack.pushContext(); |
926 |
// process namespace decls immediately; |
} |
|
// then maybe forget this as an attribute |
|
|
if (namespaces) { |
|
|
int index; |
|
|
|
|
|
// default NS declaration? |
|
|
if (getFeature (FEATURE + "string-interning")) { |
|
|
if ("xmlns" == qname) { |
|
|
declarePrefix ("", value); |
|
|
if (!xmlNames) |
|
|
return; |
|
|
} |
|
|
// NS prefix declaration? |
|
|
else if ((index = qname.indexOf (':')) == 5 |
|
|
&& qname.startsWith ("xmlns")) { |
|
|
String prefix = qname.substring (6); |
|
|
|
|
|
if (prefix.equals("")) |
|
|
fatal ("missing prefix in namespace declaration attribute"); |
|
|
if (value.length () == 0) { |
|
|
verror ("missing URI in namespace declaration attribute: " |
|
|
+ qname); |
|
|
} else |
|
|
declarePrefix (prefix, value); |
|
|
if (!xmlNames) |
|
|
return; |
|
|
} |
|
|
} else { |
|
|
if ("xmlns".equals(qname)) { |
|
|
declarePrefix ("", value); |
|
|
if (!xmlNames) |
|
|
return; |
|
|
} |
|
|
// NS prefix declaration? |
|
|
else if ((index = qname.indexOf (':')) == 5 |
|
|
&& qname.startsWith ("xmlns")) { |
|
|
String prefix = qname.substring (6); |
|
|
|
|
|
if (value.length () == 0) { |
|
|
verror ("missing URI in namespace decl attribute: " |
|
|
+ qname); |
|
|
} else |
|
|
declarePrefix (prefix, value); |
|
|
if (!xmlNames) |
|
|
return; |
|
|
} |
|
927 |
} |
} |
928 |
|
|
929 |
|
// process namespace decls immediately; |
930 |
|
// then maybe forget this as an attribute |
931 |
|
if (namespaces) |
932 |
|
{ |
933 |
|
int index; |
934 |
|
|
935 |
|
// default NS declaration? |
936 |
|
if (stringInterning) |
937 |
|
{ |
938 |
|
if ("xmlns" == qname) |
939 |
|
{ |
940 |
|
declarePrefix("", value); |
941 |
|
if (!xmlNames) |
942 |
|
{ |
943 |
|
return; |
944 |
|
} |
945 |
|
} |
946 |
|
// NS prefix declaration? |
947 |
|
else if ((index = qname.indexOf(':')) == 5 |
948 |
|
&& qname.startsWith("xmlns")) |
949 |
|
{ |
950 |
|
String prefix = qname.substring(6); |
951 |
|
|
952 |
|
if (prefix.equals("")) |
953 |
|
{ |
954 |
|
fatal("missing prefix " + |
955 |
|
"in namespace declaration attribute"); |
956 |
|
} |
957 |
|
if (value.length() == 0) |
958 |
|
{ |
959 |
|
verror("missing URI in namespace declaration attribute: " |
960 |
|
+ qname); |
961 |
|
} |
962 |
|
else |
963 |
|
{ |
964 |
|
declarePrefix(prefix, value); |
965 |
|
} |
966 |
|
if (!xmlNames) |
967 |
|
{ |
968 |
|
return; |
969 |
|
} |
970 |
|
} |
971 |
|
} |
972 |
|
else |
973 |
|
{ |
974 |
|
if ("xmlns".equals(qname)) |
975 |
|
{ |
976 |
|
declarePrefix("", value); |
977 |
|
if (!xmlNames) |
978 |
|
{ |
979 |
|
return; |
980 |
|
} |
981 |
|
} |
982 |
|
// NS prefix declaration? |
983 |
|
else if ((index = qname.indexOf(':')) == 5 |
984 |
|
&& qname.startsWith("xmlns")) |
985 |
|
{ |
986 |
|
String prefix = qname.substring(6); |
987 |
|
|
988 |
|
if (value.length() == 0) |
989 |
|
{ |
990 |
|
verror("missing URI in namespace decl attribute: " |
991 |
|
+ qname); |
992 |
|
} |
993 |
|
else |
994 |
|
{ |
995 |
|
declarePrefix(prefix, value); |
996 |
|
} |
997 |
|
if (!xmlNames) |
998 |
|
{ |
999 |
|
return; |
1000 |
|
} |
1001 |
|
} |
1002 |
|
} |
1003 |
|
} |
1004 |
|
// remember this attribute ... |
1005 |
|
attributeCount++; |
1006 |
|
|
1007 |
|
// attribute type comes from querying parser's DTD records |
1008 |
|
attributesList.add(new Attribute(qname, value, isSpecified)); |
1009 |
|
|
1010 |
} |
} |
1011 |
// remember this attribute ... |
|
1012 |
|
void startElement(String elname) |
|
attributeCount++; |
|
|
|
|
|
// attribute type comes from querying parser's DTD records |
|
|
attributesList.add(new Attribute(qname, value, isSpecified)); |
|
|
|
|
|
} |
|
|
|
|
|
void startElement (String elname) |
|
1013 |
throws SAXException |
throws SAXException |
1014 |
{ |
{ |
1015 |
ContentHandler handler = contentHandler; |
ContentHandler handler = contentHandler; |
|
|
|
|
// |
|
|
// NOTE: this implementation of namespace support adds something |
|
|
// like six percent to parsing CPU time, in a large (~50 MB) |
|
|
// document that doesn't use namespaces at all. (Measured by PC |
|
|
// sampling, with a bug where endElement processing was omitted.) |
|
|
// [Measurement referred to older implementation, older JVM ...] |
|
|
// |
|
|
// It ought to become notably faster in such cases. Most |
|
|
// costs are the prefix stack calling Hashtable.get() (2%), |
|
|
// String.hashCode() (1.5%) and about 1.3% each for pushing |
|
|
// the context, and two chunks of name processing. |
|
|
// |
|
|
|
|
|
if (!attributes) { |
|
|
if (namespaces) |
|
|
prefixStack.pushContext (); |
|
|
} else if (namespaces) { |
|
|
|
|
|
// now we can patch up namespace refs; we saw all the |
|
|
// declarations, so now we'll do the Right Thing |
|
|
Iterator itt = attributesList.iterator (); |
|
|
while(itt.hasNext()) |
|
|
{ |
|
|
Attribute attribute = (Attribute) itt.next(); |
|
|
String qname = attribute.name; |
|
|
int index; |
|
|
|
|
|
// default NS declaration? |
|
|
if (getFeature (FEATURE + "string-interning")) { |
|
|
if ("xmlns" == qname) |
|
|
continue; |
|
|
} else { |
|
|
if ("xmlns".equals(qname)) |
|
|
continue; |
|
|
} |
|
|
//Illegal in the new Namespaces Draft |
|
|
//should it be only in 1.1 docs?? |
|
|
if (qname.equals (":")) |
|
|
fatal ("namespace names consisting of a single colon " + |
|
|
"character are invalid"); |
|
|
index = qname.indexOf (':'); |
|
|
|
|
|
// NS prefix declaration? |
|
|
if (index == 5 && qname.startsWith ("xmlns")) |
|
|
continue; |
|
|
|
|
|
// it's not a NS decl; patch namespace info items |
|
|
if (prefixStack.processName (qname, nsTemp, true) == null) |
|
|
fatal ("undeclared attribute prefix in: " + qname); |
|
|
else { |
|
|
attribute.nameSpace = nsTemp[0]; |
|
|
attribute.localName = nsTemp[1]; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
// save element name so attribute callbacks work |
|
|
elementName = elname; |
|
|
if (namespaces) { |
|
|
if (prefixStack.processName (elname, nsTemp, false) == null) { |
|
|
fatal ("undeclared element prefix in: " + elname); |
|
|
nsTemp [0] = nsTemp [1] = ""; |
|
|
} |
|
|
handler.startElement (nsTemp [0], nsTemp [1], elname, this); |
|
|
} else |
|
|
handler.startElement ("", "", elname, this); |
|
|
// elementName = null; |
|
|
|
|
|
// elements with no attributes are pretty common! |
|
|
if (attributes) { |
|
|
attributesList.clear(); |
|
|
attributeCount = 0; |
|
|
attributes = false; |
|
|
} |
|
|
} |
|
1016 |
|
|
1017 |
void endElement (String elname) |
// |
1018 |
|
// NOTE: this implementation of namespace support adds something |
1019 |
|
// like six percent to parsing CPU time, in a large (~50 MB) |
1020 |
|
// document that doesn't use namespaces at all. (Measured by PC |
1021 |
|
// sampling, with a bug where endElement processing was omitted.) |
1022 |
|
// [Measurement referred to older implementation, older JVM ...] |
1023 |
|
// |
1024 |
|
// It ought to become notably faster in such cases. Most |
1025 |
|
// costs are the prefix stack calling Hashtable.get() (2%), |
1026 |
|
// String.hashCode() (1.5%) and about 1.3% each for pushing |
1027 |
|
// the context, and two chunks of name processing. |
1028 |
|
// |
1029 |
|
|
1030 |
|
if (!attributes) |
1031 |
|
{ |
1032 |
|
if (namespaces) |
1033 |
|
{ |
1034 |
|
prefixStack.pushContext(); |
1035 |
|
} |
1036 |
|
} |
1037 |
|
else if (namespaces) |
1038 |
|
{ |
1039 |
|
|
1040 |
|
// now we can patch up namespace refs; we saw all the |
1041 |
|
// declarations, so now we'll do the Right Thing |
1042 |
|
Iterator itt = attributesList.iterator(); |
1043 |
|
while (itt.hasNext()) |
1044 |
|
{ |
1045 |
|
Attribute attribute = (Attribute) itt.next(); |
1046 |
|
String qname = attribute.name; |
1047 |
|
int index; |
1048 |
|
|
1049 |
|
// default NS declaration? |
1050 |
|
if (stringInterning) |
1051 |
|
{ |
1052 |
|
if ("xmlns" == qname) |
1053 |
|
{ |
1054 |
|
continue; |
1055 |
|
} |
1056 |
|
} |
1057 |
|
else |
1058 |
|
{ |
1059 |
|
if ("xmlns".equals(qname)) |
1060 |
|
{ |
1061 |
|
continue; |
1062 |
|
} |
1063 |
|
} |
1064 |
|
//Illegal in the new Namespaces Draft |
1065 |
|
//should it be only in 1.1 docs?? |
1066 |
|
if (qname.equals (":")) |
1067 |
|
{ |
1068 |
|
fatal("namespace names consisting of a single colon " + |
1069 |
|
"character are invalid"); |
1070 |
|
} |
1071 |
|
index = qname.indexOf(':'); |
1072 |
|
|
1073 |
|
// NS prefix declaration? |
1074 |
|
if (index == 5 && qname.startsWith("xmlns")) |
1075 |
|
{ |
1076 |
|
continue; |
1077 |
|
} |
1078 |
|
|
1079 |
|
// it's not a NS decl; patch namespace info items |
1080 |
|
if (prefixStack.processName(qname, nsTemp, true) == null) |
1081 |
|
{ |
1082 |
|
fatal("undeclared attribute prefix in: " + qname); |
1083 |
|
} |
1084 |
|
else |
1085 |
|
{ |
1086 |
|
attribute.nameSpace = nsTemp[0]; |
1087 |
|
attribute.localName = nsTemp[1]; |
1088 |
|
} |
1089 |
|
} |
1090 |
|
} |
1091 |
|
|
1092 |
|
// save element name so attribute callbacks work |
1093 |
|
elementName = elname; |
1094 |
|
if (namespaces) |
1095 |
|
{ |
1096 |
|
if (prefixStack.processName(elname, nsTemp, false) == null) |
1097 |
|
{ |
1098 |
|
fatal("undeclared element prefix in: " + elname); |
1099 |
|
nsTemp[0] = nsTemp[1] = ""; |
1100 |
|
} |
1101 |
|
handler.startElement(nsTemp[0], nsTemp[1], elname, this); |
1102 |
|
} |
1103 |
|
else |
1104 |
|
{ |
1105 |
|
handler.startElement("", "", elname, this); |
1106 |
|
} |
1107 |
|
// elementName = null; |
1108 |
|
|
1109 |
|
// elements with no attributes are pretty common! |
1110 |
|
if (attributes) |
1111 |
|
{ |
1112 |
|
attributesList.clear(); |
1113 |
|
attributeCount = 0; |
1114 |
|
attributes = false; |
1115 |
|
} |
1116 |
|
} |
1117 |
|
|
1118 |
|
void endElement(String elname) |
1119 |
throws SAXException |
throws SAXException |
1120 |
{ |
{ |
1121 |
ContentHandler handler = contentHandler; |
ContentHandler handler = contentHandler; |
1122 |
|
|
1123 |
if (!namespaces) { |
if (!namespaces) |
1124 |
handler.endElement ("", "", elname); |
{ |
1125 |
return; |
handler.endElement("", "", elname); |
1126 |
} |
return; |
1127 |
prefixStack.processName (elname, nsTemp, false); |
} |
1128 |
handler.endElement (nsTemp [0], nsTemp [1], elname); |
prefixStack.processName(elname, nsTemp, false); |
1129 |
|
handler.endElement(nsTemp[0], nsTemp[1], elname); |
1130 |
Enumeration prefixes = prefixStack.getDeclaredPrefixes (); |
|
1131 |
|
Enumeration prefixes = prefixStack.getDeclaredPrefixes(); |
1132 |
while (prefixes.hasMoreElements ()) |
|
1133 |
handler.endPrefixMapping ((String) prefixes.nextElement ()); |
while (prefixes.hasMoreElements()) |
1134 |
prefixStack.popContext (); |
{ |
1135 |
} |
handler.endPrefixMapping((String) prefixes.nextElement()); |
1136 |
|
} |
1137 |
|
prefixStack.popContext(); |
1138 |
|
} |
1139 |
|
|
1140 |
void startCDATA () |
void startCDATA() |
1141 |
throws SAXException |
throws SAXException |
1142 |
{ |
{ |
1143 |
lexicalHandler.startCDATA (); |
lexicalHandler.startCDATA(); |
1144 |
} |
} |
1145 |
|
|
1146 |
void charData (char ch[], int start, int length) |
void charData(char[] ch, int start, int length) |
1147 |
throws SAXException |
throws SAXException |
1148 |
{ |
{ |
1149 |
contentHandler.characters (ch, start, length); |
contentHandler.characters(ch, start, length); |
1150 |
} |
} |
1151 |
|
|
1152 |
void endCDATA () |
void endCDATA() |
1153 |
throws SAXException |
throws SAXException |
1154 |
{ |
{ |
1155 |
lexicalHandler.endCDATA (); |
lexicalHandler.endCDATA(); |
1156 |
} |
} |
1157 |
|
|
1158 |
void ignorableWhitespace (char ch[], int start, int length) |
void ignorableWhitespace(char[] ch, int start, int length) |
1159 |
throws SAXException |
throws SAXException |
1160 |
{ |
{ |
1161 |
contentHandler.ignorableWhitespace (ch, start, length); |
contentHandler.ignorableWhitespace(ch, start, length); |
1162 |
} |
} |
1163 |
|
|
1164 |
void processingInstruction (String target, String data) |
void processingInstruction(String target, String data) |
1165 |
throws SAXException |
throws SAXException |
1166 |
{ |
{ |
1167 |
contentHandler.processingInstruction (target, data); |
contentHandler.processingInstruction(target, data); |
1168 |
} |
} |
1169 |
|
|
1170 |
void comment (char ch[], int start, int length) |
void comment(char[] ch, int start, int length) |
1171 |
throws SAXException |
throws SAXException |
1172 |
{ |
{ |
1173 |
if (lexicalHandler != base) |
if (lexicalHandler != base) |
1174 |
lexicalHandler.comment (ch, start, length); |
{ |
1175 |
} |
lexicalHandler.comment(ch, start, length); |
1176 |
|
} |
1177 |
|
} |
1178 |
|
|
1179 |
void fatal (String message) |
void fatal(String message) |
1180 |
throws SAXException |
throws SAXException |
1181 |
{ |
{ |
1182 |
SAXParseException fatal; |
SAXParseException fatal; |
1183 |
|
|
1184 |
fatal = new SAXParseException (message, this); |
fatal = new SAXParseException(message, this); |
1185 |
errorHandler.fatalError (fatal); |
errorHandler.fatalError(fatal); |
1186 |
|
|
1187 |
// Even if the application can continue ... we can't! |
// Even if the application can continue ... we can't! |
1188 |
throw fatal; |
throw fatal; |
1189 |
} |
} |
|
|
|
|
// We can safely report a few validity errors that |
|
|
// make layered SAX2 DTD validation more conformant |
|
|
void verror (String message) |
|
|
throws SAXException |
|
|
{ |
|
|
SAXParseException err; |
|
|
|
|
|
err = new SAXParseException (message, this); |
|
|
errorHandler.error (err); |
|
|
} |
|
1190 |
|
|
1191 |
void warn (String message) |
// We can safely report a few validity errors that |
1192 |
|
// make layered SAX2 DTD validation more conformant |
1193 |
|
void verror(String message) |
1194 |
|
throws SAXException |
1195 |
|
{ |
1196 |
|
SAXParseException err; |
1197 |
|
|
1198 |
|
err = new SAXParseException(message, this); |
1199 |
|
errorHandler.error(err); |
1200 |
|
} |
1201 |
|
|
1202 |
|
void warn(String message) |
1203 |
throws SAXException |
throws SAXException |
1204 |
{ |
{ |
1205 |
SAXParseException err; |
SAXParseException err; |
1206 |
|
|
1207 |
err = new SAXParseException (message, this); |
err = new SAXParseException(message, this); |
1208 |
errorHandler.warning (err); |
errorHandler.warning(err); |
1209 |
} |
} |
|
|
|
1210 |
|
|
1211 |
// |
// |
1212 |
// Implementation of org.xml.sax.Attributes. |
// Implementation of org.xml.sax.Attributes. |
1213 |
// |
// |
1214 |
|
|
1215 |
|
/** |
1216 |
|
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
1217 |
|
* (don't invoke on parser); |
1218 |
|
*/ |
1219 |
|
public int getLength() |
1220 |
|
{ |
1221 |
|
return attributesList.size(); |
1222 |
|
} |
1223 |
|
|
1224 |
/** |
/** |
1225 |
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
1226 |
* (don't invoke on parser); |
*/ |
1227 |
*/ |
public String getURI(int index) |
1228 |
public int getLength () |
{ |
1229 |
{ |
if (index < 0 || index >= attributesList.size()) |
1230 |
return attributesList.size(); |
{ |
1231 |
} |
return null; |
1232 |
|
} |
1233 |
|
return ((Attribute) attributesList.get(index)).nameSpace; |
1234 |
|
} |
1235 |
|
|
1236 |
/** |
/** |
1237 |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
1238 |
*/ |
*/ |
1239 |
public String getURI (int index) |
public String getLocalName(int index) |
1240 |
{ |
{ |
1241 |
if (index < 0 || index >= attributesList.size()) |
if (index < 0 || index >= attributesList.size()) |
1242 |
{ |
{ |
1243 |
return null; |
return null; |
1244 |
} |
} |
1245 |
return ((Attribute) attributesList.get(index)).nameSpace; |
Attribute attr = (Attribute) attributesList.get(index); |
1246 |
} |
// FIXME attr.localName is sometimes null, why? |
1247 |
|
if (namespaces && attr.localName == null) |
1248 |
|
{ |
1249 |
|
// XXX fix this here for now |
1250 |
|
int ci = attr.name.indexOf(':'); |
1251 |
|
attr.localName = (ci == -1) ? attr.name : |
1252 |
|
attr.name.substring(ci + 1); |
1253 |
|
} |
1254 |
|
return (attr.localName == null) ? "" : attr.localName; |
1255 |
|
} |
1256 |
|
|
1257 |
/** |
/** |
1258 |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
1259 |
*/ |
*/ |
1260 |
public String getLocalName (int index) |
public String getQName(int index) |
1261 |
{ |
{ |
1262 |
if (index < 0 || index >= attributesList.size()) |
if (index < 0 || index >= attributesList.size()) |
1263 |
{ |
{ |
1264 |
return null; |
return null; |
1265 |
} |
} |
1266 |
Attribute attr = (Attribute) attributesList.get(index); |
Attribute attr = (Attribute) attributesList.get(index); |
1267 |
// FIXME attr.localName is sometimes null, why? |
return (attr.name == null) ? "" : attr.name; |
1268 |
if (namespaces && attr.localName == null) |
} |
|
{ |
|
|
// XXX fix this here for now |
|
|
int ci = attr.name.indexOf(':'); |
|
|
attr.localName = (ci == -1) ? attr.name : |
|
|
attr.name.substring(ci + 1); |
|
|
} |
|
|
return (attr.localName == null) ? "" : attr.localName; |
|
|
} |
|
1269 |
|
|
1270 |
/** |
/** |
1271 |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
* <b>SAX1 AttributeList</b> method (don't invoke on parser); |
1272 |
*/ |
*/ |
1273 |
public String getQName (int index) |
public String getName(int index) |
1274 |
{ |
{ |
1275 |
if (index < 0 || index >= attributesList.size()) |
return getQName(index); |
1276 |
{ |
} |
|
return null; |
|
|
} |
|
|
Attribute attr = (Attribute) attributesList.get(index); |
|
|
return (attr.name == null) ? "" : attr.name; |
|
|
} |
|
1277 |
|
|
1278 |
/** |
/** |
1279 |
* <b>SAX1 AttributeList</b> method (don't invoke on parser); |
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
1280 |
*/ |
* (don't invoke on parser); |
1281 |
public String getName (int index) |
*/ |
1282 |
{ |
public String getType(int index) |
1283 |
return getQName(index); |
{ |
1284 |
} |
if (index < 0 || index >= attributesList.size()) |
1285 |
|
{ |
1286 |
|
return null; |
1287 |
|
} |
1288 |
|
String type = parser.getAttributeType(elementName, getQName(index)); |
1289 |
|
if (type == null) |
1290 |
|
{ |
1291 |
|
return "CDATA"; |
1292 |
|
} |
1293 |
|
// ... use DeclHandler.attributeDecl to see enumerations |
1294 |
|
if (type == "ENUMERATION") |
1295 |
|
{ |
1296 |
|
return "NMTOKEN"; |
1297 |
|
} |
1298 |
|
return type; |
1299 |
|
} |
1300 |
|
|
1301 |
/** |
/** |
1302 |
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
1303 |
* (don't invoke on parser); |
* (don't invoke on parser); |
1304 |
*/ |
*/ |
1305 |
public String getType (int index) |
public String getValue(int index) |
1306 |
{ |
{ |
1307 |
if (index < 0 || index >= attributesList.size()) |
if (index < 0 || index >= attributesList.size()) |
1308 |
{ |
{ |
1309 |
return null; |
return null; |
1310 |
} |
} |
1311 |
String type = parser.getAttributeType(elementName, getQName(index)); |
return ((Attribute) attributesList.get(index)).value; |
1312 |
if (type == null) |
} |
|
{ |
|
|
return "CDATA"; |
|
|
} |
|
|
// ... use DeclHandler.attributeDecl to see enumerations |
|
|
if (type == "ENUMERATION") |
|
|
{ |
|
|
return "NMTOKEN"; |
|
|
} |
|
|
return type; |
|
|
} |
|
1313 |
|
|
1314 |
|
/** |
1315 |
|
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
1316 |
|
*/ |
1317 |
|
public int getIndex(String uri, String local) |
1318 |
|
{ |
1319 |
|
int length = getLength(); |
1320 |
|
|
1321 |
|
for (int i = 0; i < length; i++) |
1322 |
|
{ |
1323 |
|
if (!getURI(i).equals(uri)) |
1324 |
|
{ |
1325 |
|
continue; |
1326 |
|
} |
1327 |
|
if (getLocalName(i).equals(local)) |
1328 |
|
{ |
1329 |
|
return i; |
1330 |
|
} |
1331 |
|
} |
1332 |
|
return -1; |
1333 |
|
} |
1334 |
|
|
1335 |
/** |
/** |
1336 |
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
1337 |
* (don't invoke on parser); |
*/ |
1338 |
*/ |
public int getIndex(String xmlName) |
1339 |
public String getValue (int index) |
{ |
1340 |
{ |
int length = getLength(); |
1341 |
if (index < 0 || index >= attributesList.size()) |
|
1342 |
|
for (int i = 0; i < length; i++) |
1343 |
|
{ |
1344 |
|
if (getQName(i).equals(xmlName)) |
1345 |
{ |
{ |
1346 |
return null; |
return i; |
1347 |
} |
} |
1348 |
return ((Attribute) attributesList.get(index)).value; |
} |
1349 |
} |
return -1; |
1350 |
|
} |
1351 |
|
|
1352 |
/** |
/** |
1353 |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
1354 |
*/ |
*/ |
1355 |
public int getIndex (String uri, String local) |
public String getType(String uri, String local) |
1356 |
{ |
{ |
1357 |
int length = getLength(); |
int index = getIndex(uri, local); |
1358 |
|
|
1359 |
|
if (index < 0) |
1360 |
|
{ |
1361 |
|
return null; |
1362 |
|
} |
1363 |
|
return getType(index); |
1364 |
|
} |
1365 |
|
|
1366 |
for (int i = 0; i < length; i++) |
/** |
1367 |
{ |
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
1368 |
if (!getURI(i).equals(uri)) |
* (don't invoke on parser); |
1369 |
{ |
*/ |
1370 |
continue; |
public String getType(String xmlName) |
1371 |
} |
{ |
1372 |
if (getLocalName(i).equals(local)) |
int index = getIndex(xmlName); |
1373 |
{ |
|
1374 |
return i; |
if (index < 0) |
1375 |
} |
{ |
1376 |
} |
return null; |
1377 |
return -1; |
} |
1378 |
} |
return getType(index); |
1379 |
|
} |
1380 |
|
|
1381 |
|
/** |
1382 |
|
* <b>SAX Attributes</b> method (don't invoke on parser); |
1383 |
|
*/ |
1384 |
|
public String getValue(String uri, String local) |
1385 |
|
{ |
1386 |
|
int index = getIndex(uri, local); |
1387 |
|
|
1388 |
|
if (index < 0) |
1389 |
|
{ |
1390 |
|
return null; |
1391 |
|
} |
1392 |
|
return getValue(index); |
1393 |
|
} |
1394 |
|
|
1395 |
/** |
/** |
1396 |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
1397 |
*/ |
* (don't invoke on parser); |
1398 |
public int getIndex (String xmlName) |
*/ |
1399 |
{ |
public String getValue(String xmlName) |
1400 |
int length = getLength(); |
{ |
1401 |
|
int index = getIndex(xmlName); |
1402 |
|
|
1403 |
|
if (index < 0) |
1404 |
|
{ |
1405 |
|
return null; |
1406 |
|
} |
1407 |
|
return getValue(index); |
1408 |
|
} |
1409 |
|
|
1410 |
for (int i = 0; i < length; i++) |
// |
1411 |
{ |
// Implementation of org.xml.sax.ext.Attributes2 |
1412 |
if (getQName(i).equals(xmlName)) |
// |
1413 |
{ |
|
1414 |
return i; |
/** @return false unless the attribute was declared in the DTD. |
1415 |
} |
* @throws java.lang.ArrayIndexOutOfBoundsException |
1416 |
} |
* When the supplied index does not identify an attribute. |
1417 |
return -1; |
*/ |
1418 |
} |
public boolean isDeclared(int index) |
1419 |
|
{ |
1420 |
|
if (index < 0 || index >= attributeCount) |
1421 |
|
{ |
1422 |
|
throw new ArrayIndexOutOfBoundsException(); |
1423 |
|
} |
1424 |
|
String type = parser.getAttributeType(elementName, getQName(index)); |
1425 |
|
return (type != null); |
1426 |
|
} |
1427 |
|
|
1428 |
|
/** @return false unless the attribute was declared in the DTD. |
1429 |
|
* @throws java.lang.IllegalArgumentException |
1430 |
|
* When the supplied names do not identify an attribute. |
1431 |
|
*/ |
1432 |
|
public boolean isDeclared(String qName) |
1433 |
|
{ |
1434 |
|
int index = getIndex(qName); |
1435 |
|
if (index < 0) |
1436 |
|
{ |
1437 |
|
throw new IllegalArgumentException(); |
1438 |
|
} |
1439 |
|
String type = parser.getAttributeType(elementName, qName); |
1440 |
|
return (type != null); |
1441 |
|
} |
1442 |
|
|
1443 |
/** |
/** @return false unless the attribute was declared in the DTD. |
1444 |
* <b>SAX2 Attributes</b> method (don't invoke on parser); |
* @throws java.lang.IllegalArgumentException |
1445 |
*/ |
* When the supplied names do not identify an attribute. |
1446 |
public String getType (String uri, String local) |
*/ |
1447 |
{ |
public boolean isDeclared(String uri, String localName) |
1448 |
int index = getIndex(uri, local); |
{ |
1449 |
|
int index = getIndex(uri, localName); |
1450 |
|
return isDeclared(index); |
1451 |
|
} |
1452 |
|
|
1453 |
if (index < 0) |
/** |
1454 |
{ |
* <b>SAX-ext Attributes2</b> method (don't invoke on parser); |
1455 |
return null; |
*/ |
1456 |
} |
public boolean isSpecified(int index) |
1457 |
return getType(index); |
{ |
1458 |
} |
return ((Attribute) attributesList.get(index)).specified; |
1459 |
|
} |
1460 |
|
|
1461 |
|
/** |
1462 |
|
* <b>SAX-ext Attributes2</b> method (don't invoke on parser); |
1463 |
|
*/ |
1464 |
|
public boolean isSpecified(String uri, String local) |
1465 |
|
{ |
1466 |
|
int index = getIndex (uri, local); |
1467 |
|
return isSpecified(index); |
1468 |
|
} |
1469 |
|
|
1470 |
/** |
/** |
1471 |
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
* <b>SAX-ext Attributes2</b> method (don't invoke on parser); |
1472 |
* (don't invoke on parser); |
*/ |
1473 |
*/ |
public boolean isSpecified(String xmlName) |
1474 |
public String getType (String xmlName) |
{ |
1475 |
{ |
int index = getIndex (xmlName); |
1476 |
int index = getIndex(xmlName); |
return isSpecified(index); |
1477 |
|
} |
1478 |
|
|
1479 |
if (index < 0) |
// |
1480 |
{ |
// Implementation of org.xml.sax.Locator. |
1481 |
return null; |
// |
1482 |
} |
|
1483 |
return getType(index); |
/** |
1484 |
} |
* <b>SAX Locator</b> method (don't invoke on parser); |
1485 |
|
*/ |
1486 |
|
public String getPublicId() |
1487 |
|
{ |
1488 |
|
return null; // FIXME track public IDs too |
1489 |
|
} |
1490 |
|
|
1491 |
|
/** |
1492 |
|
* <b>SAX Locator</b> method (don't invoke on parser); |
1493 |
|
*/ |
1494 |
|
public String getSystemId() |
1495 |
|
{ |
1496 |
|
if (entityStack.empty()) |
1497 |
|
{ |
1498 |
|
return null; |
1499 |
|
} |
1500 |
|
else |
1501 |
|
{ |
1502 |
|
return (String) entityStack.peek(); |
1503 |
|
} |
1504 |
|
} |
1505 |
|
|
1506 |
/** |
/** |
1507 |
* <b>SAX Attributes</b> method (don't invoke on parser); |
* <b>SAX Locator</b> method (don't invoke on parser); |
1508 |
*/ |
*/ |
1509 |
public String getValue (String uri, String local) |
public int getLineNumber() |
1510 |
{ |
{ |
1511 |
int index = getIndex(uri, local); |
return parser.getLineNumber(); |
1512 |
|
} |
1513 |
|
|
1514 |
if (index < 0) |
/** |
1515 |
{ |
* <b>SAX Locator</b> method (don't invoke on parser); |
1516 |
return null; |
*/ |
1517 |
} |
public int getColumnNumber() |
1518 |
return getValue(index); |
{ |
1519 |
} |
return parser.getColumnNumber(); |
1520 |
|
} |
1521 |
|
|
1522 |
|
// adapter between SAX2 content handler and SAX1 document handler callbacks |
1523 |
|
private static class Adapter |
1524 |
|
implements ContentHandler |
1525 |
|
{ |
1526 |
|
|
1527 |
|
private DocumentHandler docHandler; |
1528 |
|
|
1529 |
/** |
Adapter(DocumentHandler dh) |
|
* <b>SAX1 AttributeList, SAX2 Attributes</b> method |
|
|
* (don't invoke on parser); |
|
|
*/ |
|
|
public String getValue (String xmlName) |
|
1530 |
{ |
{ |
1531 |
int index = getIndex(xmlName); |
docHandler = dh; |
|
|
|
|
if (index < 0) |
|
|
{ |
|
|
return null; |
|
|
} |
|
|
return getValue(index); |
|
1532 |
} |
} |
1533 |
|
|
1534 |
|
public void setDocumentLocator(Locator l) |
|
// |
|
|
// Implementation of org.xml.sax.ext.Attributes2 |
|
|
// |
|
|
|
|
|
|
|
|
/** @return false unless the attribute was declared in the DTD. |
|
|
* @throws java.lang.ArrayIndexOutOfBoundsException |
|
|
* When the supplied index does not identify an attribute. |
|
|
*/ |
|
|
public boolean isDeclared (int index) |
|
1535 |
{ |
{ |
1536 |
if (index < 0 || index >= attributeCount) |
docHandler.setDocumentLocator(l); |
|
throw new ArrayIndexOutOfBoundsException (); |
|
|
String type = parser.getAttributeType(elementName, getQName(index)); |
|
|
return (type != null); |
|
1537 |
} |
} |
1538 |
|
|
1539 |
/** @return false unless the attribute was declared in the DTD. |
public void startDocument() |
1540 |
* @throws java.lang.IllegalArgumentException |
throws SAXException |
|
* When the supplied names do not identify an attribute. |
|
|
*/ |
|
|
public boolean isDeclared (String qName) |
|
1541 |
{ |
{ |
1542 |
int index = getIndex (qName); |
docHandler.startDocument(); |
|
if (index < 0) |
|
|
throw new IllegalArgumentException (); |
|
|
String type = parser.getAttributeType(elementName, qName); |
|
|
return (type != null); |
|
1543 |
} |
} |
1544 |
|
|
1545 |
/** @return false unless the attribute was declared in the DTD. |
public void processingInstruction(String target, String data) |
1546 |
* @throws java.lang.IllegalArgumentException |
throws SAXException |
|
* When the supplied names do not identify an attribute. |
|
|
*/ |
|
|
public boolean isDeclared (String uri, String localName) |
|
1547 |
{ |
{ |
1548 |
int index = getIndex (uri, localName); |
docHandler.processingInstruction(target, data); |
|
return isDeclared(index); |
|
1549 |
} |
} |
1550 |
|
|
1551 |
|
public void startPrefixMapping(String prefix, String uri) |
|
/** |
|
|
* <b>SAX-ext Attributes2</b> method (don't invoke on parser); |
|
|
*/ |
|
|
public boolean isSpecified (int index) |
|
1552 |
{ |
{ |
1553 |
return ((Attribute) attributesList.get(index)).specified; |
/* ignored */ |
1554 |
} |
} |
1555 |
|
|
1556 |
/** |
public void startElement(String namespace, |
1557 |
* <b>SAX-ext Attributes2</b> method (don't invoke on parser); |
String local, |
1558 |
*/ |
String name, |
1559 |
public boolean isSpecified (String uri, String local) |
Attributes attrs) |
1560 |
|
throws SAXException |
1561 |
{ |
{ |
1562 |
int index = getIndex (uri, local); |
docHandler.startElement(name, (AttributeList) attrs); |
|
return isSpecified(index); |
|
1563 |
} |
} |
1564 |
|
|
1565 |
/** |
public void characters(char[] buf, int offset, int len) |
1566 |
* <b>SAX-ext Attributes2</b> method (don't invoke on parser); |
throws SAXException |
|
*/ |
|
|
public boolean isSpecified (String xmlName) |
|
1567 |
{ |
{ |
1568 |
int index = getIndex (xmlName); |
docHandler.characters(buf, offset, len); |
|
return isSpecified(index); |
|
1569 |
} |
} |
1570 |
|
|
1571 |
|
public void ignorableWhitespace(char[] buf, int offset, int len) |
1572 |
// |
throws SAXException |
|
// Implementation of org.xml.sax.Locator. |
|
|
// |
|
|
|
|
|
/** |
|
|
* <b>SAX Locator</b> method (don't invoke on parser); |
|
|
*/ |
|
|
public String getPublicId () |
|
1573 |
{ |
{ |
1574 |
return null; // FIXME track public IDs too |
docHandler.ignorableWhitespace(buf, offset, len); |
1575 |
} |
} |
1576 |
|
|
1577 |
/** |
public void skippedEntity(String name) |
|
* <b>SAX Locator</b> method (don't invoke on parser); |
|
|
*/ |
|
|
public String getSystemId () |
|
1578 |
{ |
{ |
1579 |
if (entityStack.empty ()) |
/* ignored */ |
|
return null; |
|
|
else |
|
|
return (String) entityStack.peek (); |
|
1580 |
} |
} |
1581 |
|
|
1582 |
/** |
public void endElement(String u, String l, String name) |
1583 |
* <b>SAX Locator</b> method (don't invoke on parser); |
throws SAXException |
|
*/ |
|
|
public int getLineNumber () |
|
1584 |
{ |
{ |
1585 |
return parser.getLineNumber (); |
docHandler.endElement(name); |
1586 |
} |
} |
1587 |
|
|
1588 |
/** |
public void endPrefixMapping(String prefix) |
|
* <b>SAX Locator</b> method (don't invoke on parser); |
|
|
*/ |
|
|
public int getColumnNumber () |
|
1589 |
{ |
{ |
1590 |
return parser.getColumnNumber (); |
/* ignored */ |
1591 |
} |
} |
1592 |
|
|
1593 |
// adapter between SAX2 content handler and SAX1 document handler callbacks |
public void endDocument() |
1594 |
private static class Adapter implements ContentHandler |
throws SAXException |
1595 |
{ |
{ |
1596 |
private DocumentHandler docHandler; |
docHandler.endDocument(); |
|
|
|
|
Adapter (DocumentHandler dh) |
|
|
{ docHandler = dh; } |
|
|
|
|
|
|
|
|
public void setDocumentLocator (Locator l) |
|
|
{ docHandler.setDocumentLocator (l); } |
|
|
|
|
|
public void startDocument () throws SAXException |
|
|
{ docHandler.startDocument (); } |
|
|
|
|
|
public void processingInstruction (String target, String data) |
|
|
throws SAXException |
|
|
{ docHandler.processingInstruction (target, data); } |
|
|
|
|
|
public void startPrefixMapping (String prefix, String uri) |
|
|
{ /* ignored */ } |
|
|
|
|
|
public void startElement ( |
|
|
String namespace, |
|
|
String local, |
|
|
String name, |
|
|
Attributes attrs |
|
|
) throws SAXException |
|
|
{ docHandler.startElement (name, (AttributeList) attrs); } |
|
|
|
|
|
public void characters (char buf [], int offset, int len) |
|
|
throws SAXException |
|
|
{ docHandler.characters (buf, offset, len); } |
|
|
|
|
|
public void ignorableWhitespace (char buf [], int offset, int len) |
|
|
throws SAXException |
|
|
{ docHandler.ignorableWhitespace (buf, offset, len); } |
|
|
|
|
|
public void skippedEntity (String name) |
|
|
{ /* ignored */ } |
|
|
|
|
|
public void endElement (String u, String l, String name) |
|
|
throws SAXException |
|
|
{ docHandler.endElement (name); } |
|
|
|
|
|
public void endPrefixMapping (String prefix) |
|
|
{ /* ignored */ } |
|
|
|
|
|
public void endDocument () throws SAXException |
|
|
{ docHandler.endDocument (); } |
|
1597 |
} |
} |
1598 |
} |
} |
|
|
|
|
class Attribute |
|
|
{ |
|
1599 |
|
|
1600 |
|
private static class Attribute |
1601 |
|
{ |
1602 |
|
|
1603 |
String name; |
String name; |
1604 |
String value; |
String value; |
1605 |
String nameSpace; |
String nameSpace; |
1606 |
String localName; |
String localName; |
1607 |
boolean specified; |
boolean specified; |
1608 |
|
|
1609 |
Attribute(String name, String value, boolean specified) |
Attribute(String name, String value, boolean specified) |
1610 |
{ |
{ |
1611 |
this.name = name; |
this.name = name; |
1612 |
this.value = value; |
this.value = value; |
1613 |
this.nameSpace = ""; |
this.nameSpace = ""; |
1614 |
this.specified = specified; |
this.specified = specified; |
1615 |
} |
} |
1616 |
} |
|
1617 |
|
} |
1618 |
|
|
1619 |
|
} |