KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > event > HTMLEmitter


1 package net.sf.saxon.event;
2 import net.sf.saxon.charcode.UnicodeCharacterSet;
3 import net.sf.saxon.trans.DynamicError;
4 import net.sf.saxon.trans.XPathException;
5 import net.sf.saxon.om.FastStringBuffer;
6
7 import javax.xml.transform.OutputKeys JavaDoc;
8
9 /**
10   * This class generates HTML output
11   * @author Michael H. Kay
12   */

13
14 public class HTMLEmitter extends XMLEmitter {
15
16     /**
17     * Preferred character representations
18     */

19
20     private static final int REP_NATIVE = 0;
21     private static final int REP_ENTITY = 1;
22     private static final int REP_DECIMAL = 2;
23     private static final int REP_HEX = 3;
24
25     private int nonASCIIRepresentation = REP_NATIVE;
26     private int excludedRepresentation = REP_DECIMAL;
27     //private String mediaType = "text/html";
28
private int inScript;
29     private boolean started = false;
30     private String JavaDoc elementName;
31     private short uriCode;
32     //private boolean escapeURIAttributes = true;
33
//private boolean droppingMetaTags = false;
34

35     /**
36     * Decode preferred representation
37     */

38
39     private static int representationCode(String JavaDoc rep) {
40         if (rep.equalsIgnoreCase("native")) return REP_NATIVE;
41         if (rep.equalsIgnoreCase("entity")) return REP_ENTITY;
42         if (rep.equalsIgnoreCase("decimal")) return REP_DECIMAL;
43         if (rep.equalsIgnoreCase("hex")) return REP_HEX;
44         return REP_ENTITY;
45     }
46
47     /**
48     * Table of HTML tags that have no closing tag
49     */

50
51     static HTMLTagHashSet emptyTags = new HTMLTagHashSet(31);
52
53     static {
54         setEmptyTag("area");
55         setEmptyTag("base");
56         setEmptyTag("basefont");
57         setEmptyTag("br");
58         setEmptyTag("col");
59         setEmptyTag("frame");
60         setEmptyTag("hr");
61         setEmptyTag("img");
62         setEmptyTag("input");
63         setEmptyTag("isindex");
64         setEmptyTag("link");
65         setEmptyTag("meta");
66         setEmptyTag("param");
67     }
68
69     private static void setEmptyTag(String JavaDoc tag) {
70         emptyTags.add(tag);
71     }
72
73     protected static boolean isEmptyTag(String JavaDoc tag) {
74         return emptyTags.contains(tag);
75     }
76
77     /**
78     * Table of boolean attributes
79     */

80
81     // we use two HashMaps to avoid unnecessary string concatenations
82

83     private static HTMLTagHashSet booleanAttributes = new HTMLTagHashSet(31);
84     private static HTMLTagHashSet booleanCombinations = new HTMLTagHashSet(53);
85
86     static {
87         setBooleanAttribute("area", "nohref");
88         setBooleanAttribute("button", "disabled");
89         setBooleanAttribute("dir", "compact");
90         setBooleanAttribute("dl", "compact");
91         setBooleanAttribute("frame", "noresize");
92         setBooleanAttribute("hr", "noshade");
93         setBooleanAttribute("img", "ismap");
94         setBooleanAttribute("input", "checked");
95         setBooleanAttribute("input", "disabled");
96         setBooleanAttribute("input", "readonly");
97         setBooleanAttribute("menu", "compact");
98         setBooleanAttribute("object", "declare");
99         setBooleanAttribute("ol", "compact");
100         setBooleanAttribute("optgroup", "disabled");
101         setBooleanAttribute("option", "selected");
102         setBooleanAttribute("option", "disabled");
103         setBooleanAttribute("script", "defer");
104         setBooleanAttribute("select", "multiple");
105         setBooleanAttribute("select", "disabled");
106         setBooleanAttribute("td", "nowrap");
107         setBooleanAttribute("textarea", "disabled");
108         setBooleanAttribute("textarea", "readonly");
109         setBooleanAttribute("th", "nowrap");
110         setBooleanAttribute("ul", "compact");
111     }
112
113     private static void setBooleanAttribute(String JavaDoc element, String JavaDoc attribute) {
114         booleanAttributes.add(attribute);
115         booleanCombinations.add(element + '+' + attribute);
116     }
117
118     private static boolean isBooleanAttribute(String JavaDoc element, String JavaDoc attribute, String JavaDoc value) {
119         if (!attribute.equalsIgnoreCase(value)) return false;
120         if (!booleanAttributes.contains(attribute)) return false;
121         return booleanCombinations.contains(element + '+' + attribute);
122     }
123
124     /**
125     * Table of attributes whose value is a URL
126     */

127
128     // we use two HashMaps to avoid unnecessary string concatenations
129

130 // private static HTMLTagHashSet urlAttributes = new HTMLTagHashSet(47);
131
// private static HTMLTagHashSet urlCombinations = new HTMLTagHashSet(101);
132
//
133
// static {
134
// setUrlAttribute("form", "action");
135
// setUrlAttribute("body", "background");
136
// setUrlAttribute("q", "cite");
137
// setUrlAttribute("blockquote", "cite");
138
// setUrlAttribute("del", "cite");
139
// setUrlAttribute("ins", "cite");
140
// setUrlAttribute("object", "classid");
141
// setUrlAttribute("object", "codebase");
142
// setUrlAttribute("applet", "codebase");
143
// setUrlAttribute("object", "data");
144
// setUrlAttribute("a", "href");
145
// setUrlAttribute("a", "name"); // see second note in section B.2.1 of HTML 4 specification
146
// setUrlAttribute("area", "href");
147
// setUrlAttribute("link", "href");
148
// setUrlAttribute("base", "href");
149
// setUrlAttribute("img", "longdesc");
150
// setUrlAttribute("frame", "longdesc");
151
// setUrlAttribute("iframe", "longdesc");
152
// setUrlAttribute("head", "profile");
153
// setUrlAttribute("script", "src");
154
// setUrlAttribute("input", "src");
155
// setUrlAttribute("frame", "src");
156
// setUrlAttribute("iframe", "src");
157
// setUrlAttribute("img", "src");
158
// setUrlAttribute("img", "usemap");
159
// setUrlAttribute("input", "usemap");
160
// setUrlAttribute("object", "usemap");
161
// }
162
//
163
// private static void setUrlAttribute(String element, String attribute) {
164
// urlAttributes.add(attribute);
165
// urlCombinations.add(element + '+' + attribute);
166
// }
167
//
168
// public static boolean isUrlAttribute(String element, String attribute) {
169
// if (!urlAttributes.contains(attribute)) return false;
170
// return urlCombinations.contains(element + '+' + attribute);
171
// }
172

173     /**
174     * Constructor
175     */

176
177     public HTMLEmitter() {
178
179     }
180
181     /**
182     * Output start of document
183     */

184
185     public void open() throws XPathException {}
186
187     protected void openDocument() throws XPathException {
188         if (writer==null) {
189             makeWriter();
190         }
191         if (started) return;
192         started = true;
193             // This method is sometimes called twice, especially during an identity transform
194
// This check stops two DOCTYPE declarations being output.
195

196 // String mime = outputProperties.getProperty(OutputKeys.MEDIA_TYPE);
197
// if (mime!=null) {
198
// mediaType = mime;
199
// }
200

201         String JavaDoc byteOrderMark = outputProperties.getProperty(SaxonOutputKeys.BYTE_ORDER_MARK);
202
203         if ("yes".equals(byteOrderMark) &&
204                 "UTF-8".equalsIgnoreCase(outputProperties.getProperty(OutputKeys.ENCODING))) {
205             try {
206                 writer.write('\uFEFF');
207             } catch (java.io.IOException JavaDoc err) {
208                 // Might be an encoding exception; just ignore it
209
}
210         }
211
212         //String esc = outputProperties.getProperty(SaxonOutputKeys.ESCAPE_URI_ATTRIBUTES);
213
//escapeURIAttributes = !("no".equals(esc));
214

215         String JavaDoc systemId = outputProperties.getProperty(OutputKeys.DOCTYPE_SYSTEM);
216         String JavaDoc publicId = outputProperties.getProperty(OutputKeys.DOCTYPE_PUBLIC);
217
218         if (systemId!=null || publicId!=null) {
219             writeDocType("html", systemId, publicId);
220         }
221
222         empty = false;
223         inScript = -1000000;
224
225         String JavaDoc representation = outputProperties.getProperty(
226                                     SaxonOutputKeys.CHARACTER_REPRESENTATION);
227         if (representation!=null) {
228             String JavaDoc nonASCIIrep;
229             String JavaDoc excludedRep;
230             int semi = representation.indexOf(';');
231             if (semi < 0) {
232                 nonASCIIrep = representation;
233                 excludedRep = representation;
234             } else {
235                 nonASCIIrep = representation.substring(0, semi).trim();
236                 excludedRep = representation.substring(semi+1).trim();
237             }
238             nonASCIIRepresentation = representationCode(nonASCIIrep);
239             excludedRepresentation = representationCode(excludedRep);
240             if (excludedRepresentation==REP_NATIVE) {
241                 excludedRepresentation = REP_ENTITY;
242             }
243         }
244
245     }
246
247     /**
248     * Output element start tag
249     */

250
251     public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException {
252
253         super.startElement(nameCode, typeCode, locationId, properties);
254         uriCode = namePool.getURICode(nameCode);
255         elementName = (String JavaDoc)elementStack.peek();
256
257         if (uriCode==0 &&
258                 ( elementName.equalsIgnoreCase("script") ||
259                     elementName.equalsIgnoreCase("style"))) {
260             inScript = 0;
261         }
262         inScript++;
263     }
264
265     public void startContent() throws XPathException {
266         closeStartTag(); // prevent <xxx/> syntax
267
}
268
269     /**
270     * Write attribute name=value pair. Overrides the XML behaviour if the name and value
271     * are the same (we assume this is a boolean attribute to be minimised), or if the value is
272     * a URL.
273     */

274
275     protected void writeAttribute(int elCode, String JavaDoc attname, CharSequence JavaDoc value, int properties) throws XPathException {
276         try {
277             if (uriCode==0) {
278                 if (isBooleanAttribute(elementName, attname, value.toString())) {
279                     writer.write(attname);
280                     return;
281                 }
282 // else if (escapeURIAttributes &&
283
// isUrlAttribute(elementName, attname) &&
284
// (properties & ReceiverOptions.DISABLE_ESCAPING) == 0) {
285
// super.writeAttribute(elCode, attname, escapeURL(value), 0);
286
// return;
287
// }
288
}
289             super.writeAttribute(elCode, attname, value, properties);
290         } catch (java.io.IOException JavaDoc err) {
291             throw new DynamicError(err);
292         }
293     }
294
295
296     /**
297     * Escape characters. Overrides the XML behaviour
298     */

299
300     protected void writeEscape(final CharSequence JavaDoc chars, final boolean inAttribute)
301     throws java.io.IOException JavaDoc, XPathException {
302
303         int segstart = 0;
304         final boolean[] specialChars = (inAttribute ? specialInAtt : specialInText);
305         boolean disabled = false;
306
307         while (segstart < chars.length()) {
308             int i = segstart;
309
310             // find a maximal sequence of "ordinary" characters
311

312             while (i < chars.length() &&
313                      (chars.charAt(i)<127 ?
314                          !specialChars[chars.charAt(i)] :
315                          (characterSet.inCharset(chars.charAt(i)) ?
316                             nonASCIIRepresentation == REP_NATIVE && chars.charAt(i)>160 :
317                             false)
318                      )
319                   ) {
320                 i++;
321             }
322
323             // if this was the whole string, output the string and quit
324

325             if (i == chars.length()) {
326                 if (segstart == 0) {
327                     writeCharSequence(chars);
328                 } else {
329                     writeCharSequence(chars.subSequence(segstart, i));
330                 }
331                 return;
332             }
333
334             // otherwise, output this sequence and continue
335
if (i > segstart) {
336                 writeCharSequence(chars.subSequence(segstart, i));
337             }
338
339             final char c = chars.charAt(i);
340
341             if (c==0) {
342                 // used to switch escaping on and off
343
disabled = !disabled;
344             } else if (disabled) {
345                 writer.write(c);
346             } else if (c<=127) {
347
348                 // handle a special ASCII character
349

350                 if (inAttribute) {
351                     if (c=='<') {
352                         writer.write('<'); // not escaped
353
} else if (c=='>') {
354                         writer.write("&gt;"); // recommended for older browsers
355
} else if (c=='&') {
356                         if (i+1<chars.length() && chars.charAt(i+1)=='{') {
357                             writer.write('&'); // not escaped if followed by '{'
358
} else {
359                             writer.write("&amp;");
360                         }
361                     } else if (c=='\"') {
362                         writer.write("&#34;");
363                     } else if (c=='\n') {
364                         writer.write("&#xA;");
365                     }
366                 } else {
367                     if (c=='<') {
368                         writer.write("&lt;");
369                     } else if (c=='>') {
370                         writer.write("&gt;"); // changed to allow for "]]>"
371
} else if (c=='&') {
372                         writer.write("&amp;");
373                     }
374                 }
375
376             } else if (c==160) {
377                 // always output NBSP as an entity reference
378
writer.write("&nbsp;");
379
380             } else if (c>=127 && c<160) {
381                 // these control characters are illegal in HTML
382
DynamicError err = new DynamicError("Illegal HTML character: decimal " + (int)c);
383                 err.setErrorCode("SERE0014");
384                 throw err;
385
386             } else if (c>=55296 && c<=56319) { //handle surrogate pair
387

388                 //A surrogate pair is two consecutive Unicode characters. The first
389
//is in the range D800 to DBFF, the second is in the range DC00 to DFFF.
390
//To compute the numeric value of the character corresponding to a surrogate
391
//pair, use this formula (all numbers are hex):
392
//(FirstChar - D800) * 400 + (SecondChar - DC00) + 10000
393

394                     // we'll trust the data to be sound
395
int charval = (((int)c - 55296) * 1024) + ((int)chars.charAt(i+1) - 56320) + 65536;
396                 outputCharacterReference(charval);
397                 i++;
398
399
400             } else if (characterSet.inCharset(c)) {
401                 switch(nonASCIIRepresentation) {
402                     case REP_NATIVE:
403                         writer.write(c);
404                         break;
405                     case REP_ENTITY:
406                         if (c>160 && c<=255) {
407
408                             // if chararacter in iso-8859-1, use an entity reference
409

410                             writer.write('&');
411                             writer.write(latin1Entities[(int)c-160]);
412                             writer.write(';');
413                             break;
414                         }
415                         // else fall through
416
case REP_DECIMAL:
417                         preferHex = false;
418                         outputCharacterReference(c);
419                         break;
420                     case REP_HEX:
421                         preferHex = true;
422                         // fall through
423
default:
424                         outputCharacterReference(c);
425                         break;
426                 }
427
428             } else { // output numeric character reference
429
preferHex = (excludedRepresentation==REP_HEX);
430                 outputCharacterReference((int)c);
431             }
432
433             segstart = ++i;
434         }
435
436     }
437
438     /**
439     * Output an element end tag.
440     */

441
442     public void endElement() throws XPathException {
443         String JavaDoc name = (String JavaDoc)elementStack.peek();
444         inScript--;
445         if (inScript==0) {
446             inScript = -1000000;
447         }
448
449         if (isEmptyTag(name) && uriCode==0) {
450             // no end tag required
451
elementStack.pop();
452         } else {
453             super.endElement();
454         }
455
456     }
457
458     /**
459     * Character data.
460     */

461
462     public void characters (CharSequence JavaDoc chars, int locationId, int properties)
463     throws XPathException {
464         int options = properties;
465         if (inScript>0) {
466             options |= ReceiverOptions.DISABLE_ESCAPING;
467         }
468         super.characters(chars, locationId, options);
469     }
470
471     /**
472     * Handle a processing instruction.
473     */

474
475     public void processingInstruction (String JavaDoc target, CharSequence JavaDoc data, int locationId, int properties)
476         throws XPathException
477     {
478         if (empty) {
479             openDocument();
480         }
481         for (int i=0; i<data.length(); i++) {
482             if (data.charAt(i) == '>') {
483                 DynamicError err = new DynamicError("A processing instruction in HTML must not contain a > character");
484                 err.setErrorCode("SERE0015");
485                 throw err;
486             }
487         }
488         try {
489             writer.write("<?");
490             writer.write(target);
491             writer.write(' ');
492             writeCharSequence(data);
493             writer.write('>');
494         } catch (java.io.IOException JavaDoc err) {
495             throw new DynamicError(err);
496         }
497     }
498
499     public static CharSequence JavaDoc escapeURL(CharSequence JavaDoc url) {
500         FastStringBuffer sb = new FastStringBuffer(url.length() + 20);
501         final String JavaDoc hex = "0123456789ABCDEF";
502
503         for (int i=0; i<url.length(); i++) {
504             char ch = url.charAt(i);
505             if (ch<32 || ch>126) {
506                 byte[] array = new byte[4];
507                 int used = UnicodeCharacterSet.getUTF8Encoding(ch,
508                                                  (i+1 < url.length() ? url.charAt(i+1): ' '), array);
509                 for (int b=0; b<used; b++) {
510                     int v = (array[b]>=0 ? array[b] : 256 + array[b]);
511                     sb.append('%');
512                     sb.append(hex.charAt(v/16));
513                     sb.append(hex.charAt(v%16));
514                 }
515
516             } else {
517                 sb.append(ch);
518             }
519         }
520         return sb;
521     }
522
523
524     private static final String JavaDoc[] latin1Entities = {
525
526         "nbsp", // "&#160;" -- no-break space = non-breaking space,
527
// U+00A0 ISOnum -->
528
"iexcl", // "&#161;" -- inverted exclamation mark, U+00A1 ISOnum -->
529
"cent", // "&#162;" -- cent sign, U+00A2 ISOnum -->
530
"pound", // "&#163;" -- pound sign, U+00A3 ISOnum -->
531
"curren", // "&#164;" -- currency sign, U+00A4 ISOnum -->
532
"yen", // "&#165;" -- yen sign = yuan sign, U+00A5 ISOnum -->
533
"brvbar", // "&#166;" -- broken bar = broken vertical bar,
534
// U+00A6 ISOnum -->
535
"sect", // "&#167;" -- section sign, U+00A7 ISOnum -->
536
"uml", // "&#168;" -- diaeresis = spacing diaeresis,
537
// U+00A8 ISOdia -->
538
"copy", // "&#169;" -- copyright sign, U+00A9 ISOnum -->
539
"ordf", // "&#170;" -- feminine ordinal indicator, U+00AA ISOnum -->
540
"laquo", // "&#171;" -- left-pointing double angle quotation mark
541
// = left pointing guillemet, U+00AB ISOnum -->
542
"not", // "&#172;" -- not sign, U+00AC ISOnum -->
543
"shy", // "&#173;" -- soft hyphen = discretionary hyphen,
544
// U+00AD ISOnum -->
545
"reg", // "&#174;" -- registered sign = registered trade mark sign,
546
// U+00AE ISOnum -->
547
"macr", // "&#175;" -- macron = spacing macron = overline
548
// = APL overbar, U+00AF ISOdia -->
549
"deg", // "&#176;" -- degree sign, U+00B0 ISOnum -->
550
"plusmn", // "&#177;" -- plus-minus sign = plus-or-minus sign,
551
// U+00B1 ISOnum -->
552
"sup2", // "&#178;" -- superscript two = superscript digit two
553
// = squared, U+00B2 ISOnum -->
554
"sup3", // "&#179;" -- superscript three = superscript digit three
555
// = cubed, U+00B3 ISOnum -->
556
"acute", // "&#180;" -- acute accent = spacing acute,
557
// U+00B4 ISOdia -->
558
"micro", // "&#181;" -- micro sign, U+00B5 ISOnum -->
559
"para", // "&#182;" -- pilcrow sign = paragraph sign,
560
// U+00B6 ISOnum -->
561
"middot", // "&#183;" -- middle dot = Georgian comma
562
// = Greek middle dot, U+00B7 ISOnum -->
563
"cedil", // "&#184;" -- cedilla = spacing cedilla, U+00B8 ISOdia -->
564
"sup1", // "&#185;" -- superscript one = superscript digit one,
565
// U+00B9 ISOnum -->
566
"ordm", // "&#186;" -- masculine ordinal indicator,
567
// U+00BA ISOnum -->
568
"raquo", // "&#187;" -- right-pointing double angle quotation mark
569
// = right pointing guillemet, U+00BB ISOnum -->
570
"frac14", // "&#188;" -- vulgar fraction one quarter
571
// = fraction one quarter, U+00BC ISOnum -->
572
"frac12", // "&#189;" -- vulgar fraction one half
573
// = fraction one half, U+00BD ISOnum -->
574
"frac34", // "&#190;" -- vulgar fraction three quarters
575
// = fraction three quarters, U+00BE ISOnum -->
576
"iquest", // "&#191;" -- inverted question mark
577
// = turned question mark, U+00BF ISOnum -->
578
"Agrave", // "&#192;" -- latin capital letter A with grave
579
// = latin capital letter A grave,
580
// U+00C0 ISOlat1 -->
581
"Aacute", // "&#193;" -- latin capital letter A with acute,
582
// U+00C1 ISOlat1 -->
583
"Acirc", // "&#194;" -- latin capital letter A with circumflex,
584
// U+00C2 ISOlat1 -->
585
"Atilde", // "&#195;" -- latin capital letter A with tilde,
586
// U+00C3 ISOlat1 -->
587
"Auml", // "&#196;" -- latin capital letter A with diaeresis,
588
// U+00C4 ISOlat1 -->
589
"Aring", // "&#197;" -- latin capital letter A with ring above
590
// = latin capital letter A ring,
591
// U+00C5 ISOlat1 -->
592
"AElig", // "&#198;" -- latin capital letter AE
593
// = latin capital ligature AE,
594
// U+00C6 ISOlat1 -->
595
"Ccedil", // "&#199;" -- latin capital letter C with cedilla,
596
// U+00C7 ISOlat1 -->
597
"Egrave", // "&#200;" -- latin capital letter E with grave,
598
// U+00C8 ISOlat1 -->
599
"Eacute", // "&#201;" -- latin capital letter E with acute,
600
// U+00C9 ISOlat1 -->
601
"Ecirc", // "&#202;" -- latin capital letter E with circumflex,
602
// U+00CA ISOlat1 -->
603
"Euml", // "&#203;" -- latin capital letter E with diaeresis,
604
// U+00CB ISOlat1 -->
605
"Igrave", // "&#204;" -- latin capital letter I with grave,
606
// U+00CC ISOlat1 -->
607
"Iacute", // "&#205;" -- latin capital letter I with acute,
608
// U+00CD ISOlat1 -->
609
"Icirc", // "&#206;" -- latin capital letter I with circumflex,
610
// U+00CE ISOlat1 -->
611
"Iuml", // "&#207;" -- latin capital letter I with diaeresis,
612
// U+00CF ISOlat1 -->
613
"ETH", // "&#208;" -- latin capital letter ETH, U+00D0 ISOlat1 -->
614
"Ntilde", // "&#209;" -- latin capital letter N with tilde,
615
// U+00D1 ISOlat1 -->
616
"Ograve", // "&#210;" -- latin capital letter O with grave,
617
// U+00D2 ISOlat1 -->
618
"Oacute", // "&#211;" -- latin capital letter O with acute,
619
// U+00D3 ISOlat1 -->
620
"Ocirc", // "&#212;" -- latin capital letter O with circumflex,
621
// U+00D4 ISOlat1 -->
622
"Otilde", // "&#213;" -- latin capital letter O with tilde,
623
// U+00D5 ISOlat1 -->
624
"Ouml", // "&#214;" -- latin capital letter O with diaeresis,
625
// U+00D6 ISOlat1 -->
626
"times", // "&#215;" -- multiplication sign, U+00D7 ISOnum -->
627
"Oslash", // "&#216;" -- latin capital letter O with stroke
628
// = latin capital letter O slash,
629
// U+00D8 ISOlat1 -->
630
"Ugrave", // "&#217;" -- latin capital letter U with grave,
631
// U+00D9 ISOlat1 -->
632
"Uacute", // "&#218;" -- latin capital letter U with acute,
633
// U+00DA ISOlat1 -->
634
"Ucirc", // "&#219;" -- latin capital letter U with circumflex,
635
// U+00DB ISOlat1 -->
636
"Uuml", // "&#220;" -- latin capital letter U with diaeresis,
637
// U+00DC ISOlat1 -->
638
"Yacute", // "&#221;" -- latin capital letter Y with acute,
639
// U+00DD ISOlat1 -->
640
"THORN", // "&#222;" -- latin capital letter THORN,
641
// U+00DE ISOlat1 -->
642
"szlig", // "&#223;" -- latin small letter sharp s = ess-zed,
643
// U+00DF ISOlat1 -->
644
"agrave", // "&#224;" -- latin small letter a with grave
645
// = latin small letter a grave,
646
// U+00E0 ISOlat1 -->
647
"aacute", // "&#225;" -- latin small letter a with acute,
648
// U+00E1 ISOlat1 -->
649
"acirc", // "&#226;" -- latin small letter a with circumflex,
650
// U+00E2 ISOlat1 -->
651
"atilde", // "&#227;" -- latin small letter a with tilde,
652
// U+00E3 ISOlat1 -->
653
"auml", // "&#228;" -- latin small letter a with diaeresis,
654
// U+00E4 ISOlat1 -->
655
"aring", // "&#229;" -- latin small letter a with ring above
656
// = latin small letter a ring,
657
// U+00E5 ISOlat1 -->
658
"aelig", // "&#230;" -- latin small letter ae
659
// = latin small ligature ae, U+00E6 ISOlat1 -->
660
"ccedil", // "&#231;" -- latin small letter c with cedilla,
661
// U+00E7 ISOlat1 -->
662
"egrave", // "&#232;" -- latin small letter e with grave,
663
// U+00E8 ISOlat1 -->
664
"eacute", // "&#233;" -- latin small letter e with acute,
665
// U+00E9 ISOlat1 -->
666
"ecirc", // "&#234;" -- latin small letter e with circumflex,
667
// U+00EA ISOlat1 -->
668
"euml", // "&#235;" -- latin small letter e with diaeresis,
669
// U+00EB ISOlat1 -->
670
"igrave", // "&#236;" -- latin small letter i with grave,
671
// U+00EC ISOlat1 -->
672
"iacute", // "&#237;" -- latin small letter i with acute,
673
// U+00ED ISOlat1 -->
674
"icirc", // "&#238;" -- latin small letter i with circumflex,
675
// U+00EE ISOlat1 -->
676
"iuml", // "&#239;" -- latin small letter i with diaeresis,
677
// U+00EF ISOlat1 -->
678
"eth", // "&#240;" -- latin small letter eth, U+00F0 ISOlat1 -->
679
"ntilde", // "&#241;" -- latin small letter n with tilde,
680
// U+00F1 ISOlat1 -->
681
"ograve", // "&#242;" -- latin small letter o with grave,
682
// U+00F2 ISOlat1 -->
683
"oacute", // "&#243;" -- latin small letter o with acute,
684
// U+00F3 ISOlat1 -->
685
"ocirc", // "&#244;" -- latin small letter o with circumflex,
686
// U+00F4 ISOlat1 -->
687
"otilde", // "&#245;" -- latin small letter o with tilde,
688
// U+00F5 ISOlat1 -->
689
"ouml", // "&#246;" -- latin small letter o with diaeresis,
690
// U+00F6 ISOlat1 -->
691
"divide", // "&#247;" -- division sign, U+00F7 ISOnum -->
692
"oslash", // "&#248;" -- latin small letter o with stroke,
693
// = latin small letter o slash,
694
// U+00F8 ISOlat1 -->
695
"ugrave", // "&#249;" -- latin small letter u with grave,
696
// U+00F9 ISOlat1 -->
697
"uacute", // "&#250;" -- latin small letter u with acute,
698
// U+00FA ISOlat1 -->
699
"ucirc", // "&#251;" -- latin small letter u with circumflex,
700
// U+00FB ISOlat1 -->
701
"uuml", // "&#252;" -- latin small letter u with diaeresis,
702
// U+00FC ISOlat1 -->
703
"yacute", // "&#253;" -- latin small letter y with acute,
704
// U+00FD ISOlat1 -->
705
"thorn", // "&#254;" -- latin small letter thorn,
706
// U+00FE ISOlat1 -->
707
"yuml" // "&#255;" -- latin small letter y with diaeresis,
708
// U+00FF ISOlat1 -->
709
};
710
711
712 }
713
714 //
715
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
716
// you may not use this file except in compliance with the License. You may obtain a copy of the
717
// License at http://www.mozilla.org/MPL/
718
//
719
// Software distributed under the License is distributed on an "AS IS" basis,
720
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
721
// See the License for the specific language governing rights and limitations under the License.
722
//
723
// The Original Code is: all this file.
724
//
725
// The Initial Developer of the Original Code is Michael H. Kay.
726
//
727
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
728
//
729
// Contributor(s): none.
730
//
731
Popular Tags