1 4 package org.znerd.xmlenc; 5 6 import java.io.IOException ; 7 import java.io.UnsupportedEncodingException ; 8 import java.io.Writer ; 9 10 29 public class XMLEncoder extends Object { 30 31 110 111 115 132 public static final XMLEncoder getEncoder(String encoding) 133 throws IllegalArgumentException , UnsupportedEncodingException { 134 return new XMLEncoder(encoding); 135 } 136 137 138 142 145 private static final char[] DECLARATION_START = "<?xml version=\"1.0\" encoding=\"".toCharArray(); 146 147 150 private static final int DECLARATION_START_LENGTH = DECLARATION_START.length; 151 152 155 private static final char[] DECLARATION_END = "\"?>".toCharArray(); 156 157 160 private static final int DECLARATION_END_LENGTH = DECLARATION_END.length; 161 162 165 private static final char[] ESC_GREATER_THAN = new char[] { '&', 'g', 't', ';' }; 166 167 170 private static final char[] ESC_LESS_THAN = new char[] { '&', 'l', 't', ';' }; 171 172 175 private static final char[] ESC_AMPERSAND = new char[] { '&', 'a', 'm', 'p', ';' }; 176 177 180 private static final char[] ESC_APOSTROPHE = new char[] { '&', 'a', 'p', 'o', 's', ';' }; 181 182 185 private static final char[] ESC_QUOTE = new char[] { '&', 'q', 'u', 'o', 't', ';' }; 186 187 190 private static final char[] AMPERSAND_HASH = new char[] { '&', '#' }; 191 192 195 private static final char[] EQUALS_APOSTROPHE = new char[] { '=', '\'' }; 196 197 200 private static final char[] EQUALS_QUOTE = new char[] { '=', '"' }; 201 202 203 207 223 public XMLEncoder(String encoding) 224 throws IllegalArgumentException , UnsupportedEncodingException { 225 226 if (encoding == null) { 228 throw new IllegalArgumentException ("encoding == null"); 229 } 230 231 String ucEncoding = encoding.toUpperCase(); 234 235 if (ucEncoding.equals("UTF-8") || ucEncoding.equals("UTF-16")) { 237 _sevenBitEncoding = false; 238 239 } else if (ucEncoding.equals("US-ASCII") 241 || ucEncoding.equals("ASCII") 242 || ucEncoding.startsWith("ISO-8859-")) { 243 _sevenBitEncoding = true; 244 245 } else { 247 throw new UnsupportedEncodingException (encoding); 248 } 249 250 _encoding = encoding; 252 _encodingCharArray = encoding.toCharArray(); 253 } 254 255 256 260 263 private final String _encoding; 264 265 269 private final char[] _encodingCharArray; 270 271 277 private final boolean _sevenBitEncoding; 278 279 280 284 290 public String getEncoding() { 291 return _encoding; 292 } 293 294 306 public void declaration(Writer out) 307 throws NullPointerException , IOException { 308 out.write(DECLARATION_START, 0, DECLARATION_START_LENGTH); 309 out.write(_encodingCharArray); 310 out.write(DECLARATION_END, 0, DECLARATION_END_LENGTH); 311 } 312 313 338 public void text(Writer out, String text, boolean escapeAmpersands) 339 throws NullPointerException , InvalidXMLException, IOException { 340 341 text(out, 342 text.toCharArray(), 343 0, 344 text.length(), 345 escapeAmpersands); 346 } 347 348 387 public void text(Writer out, 388 char[] ch, 389 int start, 390 int length, 391 boolean escapeAmpersands) 392 throws NullPointerException , 393 IndexOutOfBoundsException , 394 InvalidXMLException, 395 IOException { 396 397 int end = start + length; 398 399 int lastEscaped = start; 401 402 if (_sevenBitEncoding) { 403 for (int i = start; i < end; i++) { 404 int c = (int) ch[i]; 405 406 if ((c >= 63 && c <= 127) || (c >= 39 && c <= 59) || (c >= 32 && c <= 37) || c == 10 || c == 13 || c == 61 || c == 9) { 407 continue; 408 } else if (c == 60) { 409 out.write(ch, lastEscaped, i - lastEscaped); 410 out.write(ESC_LESS_THAN, 0, 4); 411 lastEscaped = i + 1; 412 } else if (c == 62) { 413 out.write(ch, lastEscaped, i - lastEscaped); 414 out.write(ESC_GREATER_THAN, 0, 4); 415 lastEscaped = i + 1; 416 } else if (c == 38) { 417 if (escapeAmpersands) { 418 out.write(ch, lastEscaped, i - lastEscaped); 419 out.write(ESC_AMPERSAND, 0, 5); 420 lastEscaped = i + 1; 421 } 422 } else if (c > 127) { 423 out.write(ch, lastEscaped, i - lastEscaped); 424 out.write(AMPERSAND_HASH, 0, 2); 425 out.write(Integer.toString(c)); 426 out.write(';'); 427 lastEscaped = i + 1; 428 } else { 429 throw new InvalidXMLException("The character 0x" + Integer.toHexString(c) + " is not valid."); 430 } 431 } 432 433 } else { 435 for (int i = start; i < end; i++) { 436 int c = (int) ch[i]; 437 438 if (c >= 63 || (c >= 39 && c <= 59) || (c >= 32 && c <= 37) || c == 10 || c == 13 || c == 61 || c == 9) { 439 continue; 440 } else if (c == 60) { 441 out.write(ch, lastEscaped, i - lastEscaped); 442 out.write(ESC_LESS_THAN, 0, 4); 443 lastEscaped = i + 1; 444 } else if (c == 62) { 445 out.write(ch, lastEscaped, i - lastEscaped); 446 out.write(ESC_GREATER_THAN, 0, 4); 447 lastEscaped = i + 1; 448 } else if (c == 38) { 449 if (escapeAmpersands) { 450 out.write(ch, lastEscaped, i - lastEscaped); 451 out.write(ESC_AMPERSAND, 0, 5); 452 lastEscaped = i + 1; 453 } 454 } else { 455 throw new InvalidXMLException("The character 0x" + Integer.toHexString(c) + " is not valid."); 456 } 457 } 458 } 459 out.write(ch, lastEscaped, end - lastEscaped); 460 } 461 462 479 public void text(Writer out, char c) throws IOException { 480 if (_sevenBitEncoding && c > 127) { 481 out.write(AMPERSAND_HASH, 0, 2); 482 out.write(Integer.toString(c)); 483 out.write(';'); 484 } else { 485 out.write(c); 486 } 487 } 488 489 508 public void whitespace(Writer out, String s) 509 throws NullPointerException , InvalidXMLException, IOException { 510 511 char[] ch = s.toCharArray(); 512 int length = ch.length; 513 whitespace(out, ch, 0, length); 514 } 515 516 549 public void whitespace(Writer out, 550 char[] ch, 551 int start, 552 int length) 553 throws NullPointerException , 554 IndexOutOfBoundsException , 555 InvalidXMLException, 556 IOException { 557 558 XMLChecker.checkS(ch, start, length); 560 561 out.write(ch, start, length); 563 } 564 565 590 public void attribute(Writer out, 591 String name, 592 String value, 593 char quotationMark, 594 boolean escapeAmpersands) 595 throws NullPointerException , IOException { 596 597 char[] ch = value.toCharArray(); 598 int length = ch.length; 599 int start = 0; 600 int end = start + length; 601 602 604 int lastEscaped = 0; 606 607 if (quotationMark == '"') { 609 610 out.write(' '); 611 out.write(name); 612 613 out.write(EQUALS_QUOTE, 0, 2); 614 615 if (_sevenBitEncoding) { 616 for (int i = start; i < end; i++) { 617 int c = (int) ch[i]; 618 619 if ((c >= 63 && c <= 127) || (c >= 39 && c <= 59) || (c >= 32 && c <= 37 && c != 34) || c == 10 || c == 13 || c == 61 || c == 9) { 620 continue; 621 } else if (c == 60) { 622 out.write(ch, lastEscaped, i - lastEscaped); 623 out.write(ESC_LESS_THAN, 0, 4); 624 lastEscaped = i + 1; 625 } else if (c == 62) { 626 out.write(ch, lastEscaped, i - lastEscaped); 627 out.write(ESC_GREATER_THAN, 0, 4); 628 lastEscaped = i + 1; 629 } else if (c == 34) { 630 out.write(ch, lastEscaped, i - lastEscaped); 631 out.write(ESC_QUOTE, 0, 6); 632 lastEscaped = i + 1; 633 } else if (c == 38) { 634 if (escapeAmpersands) { 635 out.write(ch, lastEscaped, i - lastEscaped); 636 out.write(ESC_AMPERSAND, 0, 5); 637 lastEscaped = i + 1; 638 } 639 } else if (c > 127) { 640 out.write(ch, lastEscaped, i - lastEscaped); 641 out.write(AMPERSAND_HASH, 0, 2); 642 out.write(Integer.toString(c)); 643 out.write(';'); 644 lastEscaped = i + 1; 645 } else { 646 throw new InvalidXMLException("The character 0x" + Integer.toHexString(c) + " is not valid."); 647 } 648 } 649 650 } else { 652 for (int i = start; i < end; i++) { 653 int c = (int) ch[i]; 654 655 if (c >= 63 || (c >= 40 && c <= 59) || (c >= 32 && c <= 37) || c == 10 || c == 13 || c == 61 || c == 9) { 656 continue; 657 } else if (c == 60) { 658 out.write(ch, lastEscaped, i - lastEscaped); 659 out.write(ESC_LESS_THAN, 0, 4); 660 lastEscaped = i + 1; 661 } else if (c == 62) { 662 out.write(ch, lastEscaped, i - lastEscaped); 663 out.write(ESC_GREATER_THAN, 0, 4); 664 lastEscaped = i + 1; 665 } else if (c == 39) { 666 out.write(ch, lastEscaped, i - lastEscaped); 667 out.write(ESC_APOSTROPHE, 0, 6); 668 lastEscaped = i + 1; 669 } else if (c == 38) { 670 if (escapeAmpersands) { 671 out.write(ch, lastEscaped, i - lastEscaped); 672 out.write(ESC_AMPERSAND, 0, 5); 673 lastEscaped = i + 1; 674 } 675 } else { 676 throw new InvalidXMLException("The character 0x" + Integer.toHexString(c) + " is not valid."); 677 } 678 } 679 } 680 681 out.write(ch, lastEscaped, length - lastEscaped); 682 out.write(quotationMark); 683 684 685 } else if (quotationMark == '\'') { 687 out.write(' '); 688 out.write(name); 689 690 out.write(EQUALS_APOSTROPHE, 0, 2); 691 692 if (_sevenBitEncoding) { 693 for (int i = start; i < end; i++) { 694 int c = (int) ch[i]; 695 696 if ((c >= 63 && c <= 127) || (c >= 40 && c <= 59) || (c >= 32 && c <= 37) || c == 10 || c == 13 || c == 61 || c == 9) { 697 continue; 698 } else if (c == 60) { 699 out.write(ch, lastEscaped, i - lastEscaped); 700 out.write(ESC_LESS_THAN, 0, 4); 701 lastEscaped = i + 1; 702 } else if (c == 62) { 703 out.write(ch, lastEscaped, i - lastEscaped); 704 out.write(ESC_GREATER_THAN, 0, 4); 705 lastEscaped = i + 1; 706 } else if (c == 39) { 707 out.write(ch, lastEscaped, i - lastEscaped); 708 out.write(ESC_APOSTROPHE, 0, 6); 709 lastEscaped = i + 1; 710 } else if (c == 38) { 711 if (escapeAmpersands) { 712 out.write(ch, lastEscaped, i - lastEscaped); 713 out.write(ESC_AMPERSAND, 0, 5); 714 lastEscaped = i + 1; 715 } 716 } else if (c > 127) { 717 out.write(ch, lastEscaped, i - lastEscaped); 718 out.write(AMPERSAND_HASH, 0, 2); 719 out.write(Integer.toString(c)); 720 out.write(';'); 721 lastEscaped = i + 1; 722 } else { 723 throw new InvalidXMLException("The character 0x" + Integer.toHexString(c) + " is not valid."); 724 } 725 } 726 727 } else { 729 for (int i = start; i < end; i++) { 730 int c = (int) ch[i]; 731 732 if (c >= 63 || (c >= 40 && c <= 59) || (c >= 32 && c <= 37) || c == 10 || c == 13 || c == 61 || c == 9) { 733 continue; 734 } else if (c == 60) { 735 out.write(ch, lastEscaped, i - lastEscaped); 736 out.write(ESC_LESS_THAN, 0, 4); 737 lastEscaped = i + 1; 738 } else if (c == 62) { 739 out.write(ch, lastEscaped, i - lastEscaped); 740 out.write(ESC_GREATER_THAN, 0, 4); 741 lastEscaped = i + 1; 742 } else if (c == 39) { 743 out.write(ch, lastEscaped, i - lastEscaped); 744 out.write(ESC_APOSTROPHE, 0, 6); 745 lastEscaped = i + 1; 746 } else if (c == 38) { 747 if (escapeAmpersands) { 748 out.write(ch, lastEscaped, i - lastEscaped); 749 out.write(ESC_AMPERSAND, 0, 5); 750 lastEscaped = i + 1; 751 } 752 } else { 753 throw new InvalidXMLException("The character 0x" + Integer.toHexString(c) + " is not valid."); 754 } 755 } 756 } 757 758 out.write(ch, lastEscaped, length - lastEscaped); 759 out.write(quotationMark); 760 761 } else { 763 String error = "Character 0x" 764 + Integer.toHexString((int) quotationMark) 765 + " ('" 766 + quotationMark 767 + "') is not a valid quotation mark."; 768 throw new IllegalArgumentException (error); 769 } 770 } 771 } 772 | Popular Tags |