1 28 29 package net.n3.nanoxml; 30 31 import java.io.Reader ; 32 import java.util.Enumeration ; 33 import java.util.Properties ; 34 35 41 public class StdXMLParser implements IXMLParser 42 { 43 44 47 private static final char[] END_OF_PI = { '>', '?'}; 48 49 52 private static final char[] END_OF_CDATA = { '>', ']', ']'}; 53 54 57 private static final char[] END_OF_PCDATA = { '<'}; 58 59 62 private IXMLBuilder builder; 63 64 67 private IXMLReader reader; 68 69 72 private IXMLEntityResolver entityResolver; 73 74 77 private IXMLValidator validator; 78 79 82 public StdXMLParser() 83 { 84 this.builder = null; 85 this.validator = null; 86 this.reader = null; 87 this.entityResolver = new XMLEntityResolver(); 88 } 89 90 93 protected void finalize() throws Throwable 94 { 95 this.builder = null; 96 this.reader = null; 97 this.entityResolver = null; 98 this.validator = null; 99 super.finalize(); 100 } 101 102 107 public void setBuilder(IXMLBuilder builder) 108 { 109 this.builder = builder; 110 } 111 112 117 public IXMLBuilder getBuilder() 118 { 119 return this.builder; 120 } 121 122 127 public void setValidator(IXMLValidator validator) 128 { 129 this.validator = validator; 130 } 131 132 137 public IXMLValidator getValidator() 138 { 139 return this.validator; 140 } 141 142 147 public void setResolver(IXMLEntityResolver resolver) 148 { 149 this.entityResolver = resolver; 150 } 151 152 157 public IXMLEntityResolver getResolver() 158 { 159 return this.entityResolver; 160 } 161 162 167 public void setReader(IXMLReader reader) 168 { 169 this.reader = reader; 170 } 171 172 177 public IXMLReader getReader() 178 { 179 return this.reader; 180 } 181 182 189 public Object parse() throws XMLException 190 { 191 try 192 { 193 this.builder.startBuilding(this.reader.getSystemID(), this.reader.getLineNr()); 194 this.scanData(); 195 return this.builder.getResult(); 196 } 197 catch (XMLException e) 198 { 199 throw e; 200 } 201 catch (Exception e) 202 { 203 throw new XMLException(e); 204 } 205 } 206 207 212 protected void scanData() throws Exception 213 { 214 while ((!this.reader.atEOF()) && (this.builder.getResult() == null)) 215 { 216 char ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 217 218 switch (ch) 219 { 220 case '<': 221 this.scanSomeTag(false ); 222 break; 223 224 case ' ': 225 case '\t': 226 case '\r': 227 case '\n': 228 break; 230 231 default: 232 XMLUtil.errorInvalidInput(reader.getSystemID(), reader.getLineNr(), "`" + ch 233 + "' (0x" + Integer.toHexString((int) ch) + ')'); 234 } 235 } 236 } 237 238 245 protected void scanSomeTag(boolean allowCDATA) throws Exception 246 { 247 char ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 248 249 switch (ch) 250 { 251 case '?': 252 this.processPI(); 253 break; 254 255 case '!': 256 this.processSpecialTag(allowCDATA); 257 break; 258 259 default: 260 this.reader.unread(ch); 261 this.processElement(); 262 } 263 } 264 265 270 protected void processPI() throws Exception 271 { 272 XMLUtil.skipWhitespace(this.reader, '&', null, null); 273 String target = XMLUtil.scanIdentifier(this.reader, '&', this.entityResolver); 274 XMLUtil.skipWhitespace(this.reader, '&', null, null); 275 Reader reader = new ContentReader(this.reader, this.entityResolver, '&', 276 StdXMLParser.END_OF_PI, true, ""); 277 278 if (!"xml".equalsIgnoreCase(target)) 279 { 280 this.builder.newProcessingInstruction(target, reader); 281 } 282 283 reader.close(); 284 } 285 286 293 protected void processSpecialTag(boolean allowCDATA) throws Exception 294 { 295 char ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 296 297 switch (ch) 298 { 299 case '[': 300 if (allowCDATA) 301 { 302 this.processCDATA(); 303 } 304 else 305 { 306 XMLUtil.skipTag(this.reader, '&', this.entityResolver); 307 } 308 309 return; 310 311 case 'D': 312 this.processDocType(); 313 return; 314 315 case '-': 316 XMLUtil.skipComment(this.reader, this.entityResolver); 317 } 318 } 319 320 325 protected void processCDATA() throws Exception 326 { 327 if (!XMLUtil.checkLiteral(this.reader, '&', this.entityResolver, "CDATA[")) 328 { 329 XMLUtil.skipTag(this.reader, '&', this.entityResolver); 330 return; 331 } 332 333 this.validator.PCDataAdded(this.reader.getSystemID(), this.reader.getLineNr()); 334 Reader reader = new ContentReader(this.reader, this.entityResolver, '&', 335 StdXMLParser.END_OF_CDATA, true, ""); 336 337 this.builder.addPCData(reader, this.reader.getSystemID(), this.reader.getLineNr()); 338 reader.close(); 339 } 340 341 346 protected void processDocType() throws Exception 347 { 348 if (!XMLUtil.checkLiteral(this.reader, '&', this.entityResolver, "OCTYPE")) 349 { 350 XMLUtil.skipTag(this.reader, '&', this.entityResolver); 351 return; 352 } 353 354 XMLUtil.skipWhitespace(this.reader, '&', null, null); 355 String systemID = null; 356 StringBuffer publicID = new StringBuffer (); 357 XMLUtil.skipWhitespace(this.reader, '&', null, null); 358 char ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 359 360 if (ch == 'P') 361 { 362 systemID = XMLUtil.scanPublicID(publicID, reader, '&', this.entityResolver); 363 XMLUtil.skipWhitespace(this.reader, '&', null, null); 364 ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 365 } 366 else if (ch == 'S') 367 { 368 systemID = XMLUtil.scanSystemID(reader, '&', this.entityResolver); 369 XMLUtil.skipWhitespace(this.reader, '&', null, null); 370 ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 371 } 372 373 if (ch == '[') 374 { 375 this.validator.parseDTD(publicID.toString(), this.reader, this.entityResolver, false); 376 XMLUtil.skipWhitespace(this.reader, '&', null, null); 377 ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 378 } 379 380 if (ch != '>') 381 { 382 XMLUtil.errorExpectedInput(reader.getSystemID(), reader.getLineNr(), "`>'"); 383 } 384 385 if (systemID != null) 386 { 387 Reader reader = this.reader.openStream(publicID.toString(), systemID); 388 this.reader.startNewStream(reader); 389 this.reader.setSystemID(systemID); 390 this.reader.setPublicID(publicID.toString()); 391 this.validator.parseDTD(publicID.toString(), this.reader, this.entityResolver, true); 392 } 393 } 394 395 400 protected void processElement() throws Exception 401 { 402 String name = XMLUtil.scanIdentifier(this.reader, '&', this.entityResolver); 403 XMLUtil.skipWhitespace(this.reader, '&', null, null); 404 String prefix = null; 405 int colonIndex = name.indexOf(':'); 406 407 if (colonIndex > 0) 408 { 409 prefix = name.substring(0, colonIndex); 410 name = name.substring(colonIndex + 1); 411 } 412 413 this.validator.elementStarted(name, prefix, null, this.reader.getSystemID(), this.reader 414 .getLineNr()); 415 this.builder.startElement(name, prefix, null, this.reader.getSystemID(), this.reader 416 .getLineNr()); 417 char ch; 418 419 for (;;) 420 { 421 ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 422 423 if ((ch == '/') || (ch == '>')) 424 { 425 break; 426 } 427 428 this.reader.unread(ch); 429 this.processAttribute(); 430 XMLUtil.skipWhitespace(this.reader, '&', null, null); 431 } 432 433 Properties extraAttributes = new Properties (); 434 this.validator.elementAttributesProcessed(name, prefix, null, extraAttributes, this.reader 435 .getSystemID(), this.reader.getLineNr()); 436 Enumeration enumeration = extraAttributes.keys(); 437 438 while (enumeration.hasMoreElements()) 439 { 440 String key = (String ) enumeration.nextElement(); 441 String value = extraAttributes.getProperty(key); 442 String attPrefix = null; 443 colonIndex = key.indexOf(':'); 444 445 if (colonIndex > 0) 446 { 447 attPrefix = key.substring(0, colonIndex); 448 key = key.substring(colonIndex + 1); 449 } 450 451 this.builder.addAttribute(key, attPrefix, null, value, "CDATA"); 452 } 453 454 this.builder.elementAttributesProcessed(name, prefix, null); 455 456 if (ch == '/') 457 { 458 if (XMLUtil.read(this.reader, null, '&', this.entityResolver) != '>') 459 { 460 XMLUtil.errorExpectedInput(reader.getSystemID(), reader.getLineNr(), "`>'"); 461 } 462 463 this.validator.elementEnded(name, prefix, null, this.reader.getSystemID(), this.reader 464 .getLineNr()); 465 this.builder.endElement(name, prefix, null); 466 return; 467 } 468 469 StringBuffer whitespaceBuffer = new StringBuffer (16); 470 471 for (;;) 472 { 473 whitespaceBuffer.setLength(0); 474 boolean fromEntity[] = new boolean[1]; 475 XMLUtil.skipWhitespace(this.reader, '&', whitespaceBuffer, fromEntity); 476 ch = XMLUtil.read(this.reader, null, '&', this.entityResolver); 477 478 if ((ch == '<') && (!fromEntity[0])) 479 { 480 ch = reader.read(); 481 482 if (ch == '/') 483 { 484 XMLUtil.skipWhitespace(this.reader, '&', null, null); 485 String str = XMLUtil.scanIdentifier(this.reader, '&', this.entityResolver); 486 487 if (!str.equals(name)) 488 { 489 XMLUtil.errorWrongClosingTag(reader.getSystemID(), reader.getLineNr(), 490 name, str); 491 } 492 493 XMLUtil.skipWhitespace(this.reader, '&', null, null); 494 495 if (XMLUtil.read(this.reader, null, '&', this.entityResolver) != '>') 496 { 497 XMLUtil.errorClosingTagNotEmpty(reader.getSystemID(), reader.getLineNr()); 498 } 499 500 this.validator.elementEnded(name, prefix, null, this.reader.getSystemID(), 501 this.reader.getLineNr()); 502 this.builder.endElement(name, prefix, null); 503 break; 504 } 505 else 506 { 507 this.reader.unread(ch); 508 this.scanSomeTag(true ); 509 } 510 } 511 else 512 { 513 this.validator.PCDataAdded(this.reader.getSystemID(), this.reader.getLineNr()); 514 this.reader.unread(ch); 515 Reader reader = new ContentReader(this.reader, this.entityResolver, '&', 516 StdXMLParser.END_OF_PCDATA, false, whitespaceBuffer.toString()); 517 this.builder.addPCData(reader, this.reader.getSystemID(), this.reader.getLineNr()); 518 reader.close(); 519 this.reader.unread('<'); 520 } 521 } 522 } 523 524 529 protected void processAttribute() throws Exception 530 { 531 String key = XMLUtil.scanIdentifier(this.reader, '&', this.entityResolver); 532 XMLUtil.skipWhitespace(this.reader, '&', null, null); 533 534 if (XMLUtil.read(this.reader, null, '&', this.entityResolver) != '=') 535 { 536 XMLUtil.errorExpectedInput(reader.getSystemID(), reader.getLineNr(), "`='"); 537 } 538 539 String value = XMLUtil.scanString(this.reader, '&', true, this.entityResolver); 540 this.validator.attributeAdded(key, null, null, value, this.reader.getSystemID(), 541 this.reader.getLineNr()); 542 this.builder.addAttribute(key, null, null, value, "CDATA"); 543 } 544 545 } 546 | Popular Tags |