KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icesoft > faces > util > DOMUtils


1 /*
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * "The contents of this file are subject to the Mozilla Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
11  * License for the specific language governing rights and limitations under
12  * the License.
13  *
14  * The Original Code is ICEfaces 1.5 open source software code, released
15  * November 5, 2006. The Initial Developer of the Original Code is ICEsoft
16  * Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
17  * 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
18  *
19  * Contributor(s): _____________________.
20  *
21  * Alternatively, the contents of this file may be used under the terms of
22  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
23  * License), in which case the provisions of the LGPL License are
24  * applicable instead of those above. If you wish to allow use of your
25  * version of this file only under the terms of the LGPL License and not to
26  * allow others to use your version of this file under the MPL, indicate
27  * your decision by deleting the provisions above and replace them with
28  * the notice and other provisions required by the LGPL License. If you do
29  * not delete the provisions above, a recipient may use your version of
30  * this file under either the MPL or the LGPL License."
31  *
32  */

33
34 package com.icesoft.faces.util;
35
36 import org.w3c.dom.*;
37
38 import javax.faces.component.UIComponent;
39 import java.util.List JavaDoc;
40 import java.util.Vector JavaDoc;
41
42 public class DOMUtils {
43     private static int DEFAULT_DOM_STRING_PRESIZE = 4096;
44     private static int DEFAULT_NODE_STRING_PRESIZE = 256;
45     
46     public static String JavaDoc DocumentTypetoString(String JavaDoc publicID, String JavaDoc systemID,
47                                               String JavaDoc root) {
48         return "<!DOCTYPE " + root + " PUBLIC \"" + publicID + "\" \"" +
49                systemID + "\">";
50     }
51
52     public static String JavaDoc DOMtoString(Document document) {
53         return printNode(
54                 document,
55                 new StringBuffer JavaDoc(DEFAULT_DOM_STRING_PRESIZE));
56     }
57
58     public static String JavaDoc nodeToString(Node node) {
59         return printNode(
60                 node,
61                 new StringBuffer JavaDoc(DEFAULT_NODE_STRING_PRESIZE));
62     }
63
64     public static String JavaDoc childrenToString(Node node) {
65         NodeList children = node.getChildNodes();
66         Node child;
67         StringBuffer JavaDoc stringbuffer =
68                 new StringBuffer JavaDoc(DEFAULT_DOM_STRING_PRESIZE);
69         int l = children.getLength();
70         for (int i = 0; i < l; i++) {
71             child = children.item(i);
72             stringbuffer.append(nodeToString(child));
73         }
74         return stringbuffer.toString();
75     }
76
77     private static String JavaDoc printNode(Node node, StringBuffer JavaDoc stringbuffer) {
78         printNode(node, stringbuffer, 0, true, false);
79         return stringbuffer.toString();
80     }
81
82     private static void printNode(
83             Node node, StringBuffer JavaDoc stringbuffer,
84             int depth, boolean allowAddingWhitespace,
85             boolean addTrailingNewline) {
86
87         switch (node.getNodeType()) {
88
89             case Node.DOCUMENT_NODE:
90                 //stringbuffer.append("<xml version=\"1.0\">\n");
91
// recurse on each child
92
NodeList nodes = node.getChildNodes();
93                 if (nodes != null) {
94                     for (int i = 0; i < nodes.getLength(); i++) {
95                         printNode(nodes.item(i), stringbuffer, depth + 1,
96                                   allowAddingWhitespace, false);
97                     }
98                 }
99                 break;
100
101             case Node.ELEMENT_NODE:
102                 String JavaDoc name = node.getNodeName();
103                 if (name.equalsIgnoreCase("br")) {
104                     stringbuffer.append("<br>");
105                     break;
106                 }
107                 stringbuffer.append("<");
108                 stringbuffer.append(name);
109                 NamedNodeMap attributes = node.getAttributes();
110                 for (int i = 0; i < attributes.getLength(); i++) {
111                     Node current = attributes.item(i);
112                     stringbuffer.append(" ");
113                     stringbuffer.append(current.getNodeName());
114                     stringbuffer.append("=\"");
115                     stringbuffer.append(escapeAnsi(current.getNodeValue()));
116                     stringbuffer.append("\"");
117                 }
118
119                 //recognize empty elements and close them
120
//Fine for XML, but confuses some browsers
121
/*
122                 if ( !node.hasChildNodes() )
123                 {
124                     stringbuffer.append(" />\n");
125                     break;
126                 }
127                 */

128
129                 stringbuffer.append(">");
130                 // recurse on each child
131
NodeList children = node.getChildNodes();
132
133                 if (children != null) {
134                     int childrenLength = children.getLength();
135                     for (int i = 0; i < childrenLength; i++) {
136                         boolean childAddTrailingNewline = false;
137                         if (allowAddingWhitespace) {
138                             if ((i + 1) < childrenLength) {
139                                 Node nextChild = children.item(i + 1);
140                                 // We don't add the newline if the next tag is a TD,
141
// because when rendering our tabbedPane, if there's
142
// any whitespace between the adjacent TDs, then
143
// Internet Explorer will add vertical spacing
144
childAddTrailingNewline =
145                                         !isWhitespaceText(nextChild) &&
146                                         !isTD(nextChild);
147                             }
148                         }
149                         printNode(children.item(i), stringbuffer, depth + 1,
150                                   allowAddingWhitespace,
151                                   childAddTrailingNewline);
152                     }
153                 }
154
155                 stringbuffer.append("</");
156                 stringbuffer.append(name);
157                 stringbuffer.append(">");
158                 if (allowAddingWhitespace && addTrailingNewline)
159                     stringbuffer.append("\n");
160                 break;
161
162             case Node.TEXT_NODE:
163                 stringbuffer.append(node.getNodeValue());
164                 break;
165         }
166     }
167
168     private static boolean isWhitespaceText(Node node) {
169         if (node.getNodeType() == Node.TEXT_NODE) {
170             String JavaDoc val = node.getNodeValue();
171             // Treat an empty string like whitespace
172
for (int i = val.length() - 1; i >= 0; i--) {
173                 if (!Character.isWhitespace(val.charAt(i)))
174                     return false;
175             }
176             return true;
177         }
178         return false;
179     }
180
181     private static boolean isTD(Node node) {
182         if (node.getNodeType() == Node.ELEMENT_NODE) {
183             String JavaDoc name = node.getNodeName();
184             if (name != null && name.equalsIgnoreCase("td"))
185                 return true;
186         }
187         return false;
188     }
189
190     /* Return the first child of the given nodeName under the given node.
191      * @param node node to search under
192      * @param name nodeName to search for
193      */

194     public static Node getChildByNodeName(Node node, String JavaDoc name) {
195         NodeList children = node.getChildNodes();
196         Node child;
197         int l = children.getLength();
198         for (int i = 0; i < l; i++) {
199             child = children.item(i);
200             if (child.getNodeName().equalsIgnoreCase(name)) {
201                 return child;
202             }
203         }
204         return null;
205     }
206
207     /**
208      * Determine the set of top-level nodes in newDOM that are different from
209      * the corresponding nodes in oldDOM.
210      *
211      * @param oldDOM original dom Document
212      * @param newDOM changed dom Document
213      * @return array of top-level nodes in newDOM that differ from oldDOM
214      */

215     public static Node[] domDiff(Document oldDOM, Document newDOM) {
216         List JavaDoc nodeDiffs = new Vector JavaDoc();
217         compareNodes(nodeDiffs, oldDOM.getDocumentElement(),
218                      newDOM.getDocumentElement());
219         return ((Node[]) nodeDiffs.toArray(new Node[0]));
220     }
221
222
223     /**
224      * Nodes are equivalent if they have the same names, attributes, and
225      * children
226      *
227      * @param oldNode
228      * @param newNode
229      * @return true if oldNode and newNode are equivalent
230      */

231     public static boolean compareNodes(List JavaDoc nodeDiffs,
232                                        Node oldNode, Node newNode) {
233         if (!oldNode.getNodeName().equals(newNode.getNodeName())) {
234             //parent node needs to fix this
235
nodeDiffs.add(newNode.getParentNode());
236             return false;
237         }
238         if (!compareIDs(oldNode, newNode)) {
239             //parent node needs to fix this
240
nodeDiffs.add(newNode.getParentNode());
241             return false;
242         }
243         if (!compareAttributes(oldNode, newNode)) {
244             nodeDiffs.add(newNode);
245             return false;
246         }
247         if (!compareStrings(oldNode.getNodeValue(),
248                             newNode.getNodeValue())) {
249             //might not have an id
250
nodeDiffs.add(newNode);
251             return false;
252         }
253
254         NodeList oldChildNodes = oldNode.getChildNodes();
255         NodeList newChildNodes = newNode.getChildNodes();
256
257         int oldChildLength = oldChildNodes.getLength();
258         int newChildLength = newChildNodes.getLength();
259
260         if (oldChildLength != newChildLength) {
261             nodeDiffs.add(newNode);
262             return false;
263         }
264
265         boolean allChildrenMatch = true;
266         for (int i = 0; i < newChildLength; i++) {
267             if (!compareNodes(nodeDiffs, oldChildNodes.item(i),
268                               newChildNodes.item(i))) {
269                 allChildrenMatch = false;
270             }
271         }
272
273         return allChildrenMatch;
274     }
275
276     private static boolean compareStrings(String JavaDoc oldString, String JavaDoc newString) {
277         if ((null == oldString) && (null == newString)) {
278             return true;
279         }
280         try {
281             return (oldString.equals(newString));
282         } catch (NullPointerException JavaDoc e) {
283         }
284         return false;
285     }
286
287     /**
288      * @param oldNode
289      * @param newNode
290      * @return true if Nodes have the same IDs
291      */

292     public static boolean compareIDs(Node oldNode, Node newNode) {
293         if (!(oldNode instanceof Element) &&
294             !(newNode instanceof Element)) {
295             //both do not have an ID
296
return true;
297         }
298         try {
299             return ((Element) oldNode).getAttribute("id").equals(
300                     ((Element) newNode).getAttribute("id"));
301         } catch (Exception JavaDoc e) {
302         }
303         return false;
304     }
305
306     /**
307      * @param oldNode
308      * @param newNode
309      * @return true if Nodes have the same attributes
310      */

311     public static boolean compareAttributes(Node oldNode, Node newNode) {
312         boolean oldHasAttributes = oldNode.hasAttributes();
313         boolean newHasAttributes = newNode.hasAttributes();
314
315         if (!oldHasAttributes && !newHasAttributes) {
316             return true;
317         }
318         if (oldHasAttributes != newHasAttributes) {
319             return false;
320         }
321
322         NamedNodeMap oldMap = oldNode.getAttributes();
323         NamedNodeMap newMap = newNode.getAttributes();
324
325         int oldLength = oldMap.getLength();
326         int newLength = newMap.getLength();
327
328         if (oldLength != newLength) {
329             return false;
330         }
331
332         Node newAttribute = null;
333         Node oldAttribute = null;
334         for (int i = 0; i < newLength; i++) {
335             newAttribute = newMap.item(i);
336             oldAttribute = oldMap.getNamedItem(newAttribute.getNodeName());
337             if (null == oldAttribute) {
338                 return false;
339             }
340             if (!(String.valueOf(oldAttribute.getNodeValue()).equals(
341                     String.valueOf(newAttribute.getNodeValue())))) {
342                 return false;
343             }
344         }
345
346         return true;
347
348     }
349
350     public static Element ascendToNodeWithID(Node node) {
351         while (null != node) {
352             if (node instanceof Element) {
353                 String JavaDoc id = ((Element) node).getAttribute("id");
354                 if ((null != id) && (!"".equals(id))) {
355                     return (Element) node;
356                 }
357             }
358             node = node.getParentNode();
359         }
360         //it's going to be null at this point
361
return (Element) node;
362     }
363
364     /**
365      * Escaping is required unless the escape attribute is present and is
366      * "false"
367      *
368      * @param uiComponent
369      * @param valueTextRequiresEscape
370      * @return
371      */

372     public static boolean escapeIsRequired(UIComponent uiComponent) {
373         Object JavaDoc escapeAttribute = uiComponent.getAttributes().get("escape");
374         if (escapeAttribute != null) {
375             if (escapeAttribute instanceof String JavaDoc) {
376                 return Boolean.valueOf((String JavaDoc) escapeAttribute).booleanValue();
377             } else if (escapeAttribute instanceof Boolean JavaDoc) {
378                 return ((Boolean JavaDoc) escapeAttribute).booleanValue();
379             }
380         }
381         return true; //default
382
}
383
384     public static String JavaDoc escapeAnsi(String JavaDoc text) {
385     if(null == text){
386         return "";
387         }
388         char[] chars = text.toCharArray();
389         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(chars.length);
390         for (int index = 0; index < chars.length; index++) {
391             char ch = chars[index];
392             //see: http://www.w3schools.com/tags/ref_ascii.asp
393
if (ch <= 31) {
394                 if (ch == '\t' || ch == '\n' || ch == '\r') {
395                     buffer.append(ch);
396                 }
397                 //skip any other control character
398
} else if (ch == 127) {
399                 //skip 'escape' character
400
} else if (ch == '>') {
401                 buffer.append("&gt;");
402             } else if (ch == '<') {
403                 buffer.append("&lt;");
404             } else if (ch == '&') {
405                 buffer.append("&amp;");
406             } else if (ch == '\'') {
407                 buffer.append("&#39;");
408             } else if (ch == '"') {
409                 buffer.append("&quot;");
410             } else if (ch >= 0xA0 && ch <= 0xff) {
411                 buffer.append("&" + escapeAnsi(ch) + ";");
412             } else if (ch == 0x20AC) {//special case for euro symbol
413
buffer.append("&euro;");
414             } else {
415                 buffer.append(ch);
416             }
417         }
418
419         return buffer.toString();
420     }
421
422     /**
423      * @param character
424      * @return
425      */

426     private static String JavaDoc escapeAnsi(char character) {
427         int indexOfEscapedCharacter = character - 0xA0;
428         return ansiCharacters[indexOfEscapedCharacter];
429     }
430
431     /**
432      * from http://www.w3.org/TR/REC-html40/sgml/entities.html
433      Portions Copyright International Organization for Standardization 1986
434      Permission to copy in any form is granted for use with
435      conforming SGML systems and applications as defined in
436      ISO 8879, provided this notice is included in all copies.
437     */

438     private static String JavaDoc[] ansiCharacters = new String JavaDoc[]{
439             "nbsp"
440             /* "&#160;" -- no-break space = non-breaking space, U+00A0 ISOnum -->*/,
441             "iexcl" /* "&#161;" -- inverted exclamation mark, U+00A1 ISOnum */,
442             "cent" /* "&#162;" -- cent sign, U+00A2 ISOnum */,
443             "pound" /* "&#163;" -- pound sign, U+00A3 ISOnum */,
444             "curren" /* "&#164;" -- currency sign, U+00A4 ISOnum */,
445             "yen" /* "&#165;" -- yen sign = yuan sign, U+00A5 ISOnum */,
446             "brvbar"
447             /* "&#166;" -- broken bar = broken vertical bar, U+00A6 ISOnum */,
448             "sect" /* "&#167;" -- section sign, U+00A7 ISOnum */,
449             "uml"
450             /* "&#168;" -- diaeresis = spacing diaeresis, U+00A8 ISOdia */,
451             "copy" /* "&#169;" -- copyright sign, U+00A9 ISOnum */,
452             "ordf"
453             /* "&#170;" -- feminine ordinal indicator, U+00AA ISOnum */,
454             "laquo"
455             /* "&#171;" -- left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum */,
456             "not" /* "&#172;" -- not sign, U+00AC ISOnum */,
457             "shy"
458             /* "&#173;" -- soft hyphen = discretionary hyphen, U+00AD ISOnum */,
459             "reg"
460             /* "&#174;" -- registered sign = registered trade mark sign, U+00AE ISOnum */,
461             "macr"
462             /* "&#175;" -- macron = spacing macron = overline = APL overbar, U+00AF ISOdia */,
463             "deg" /* "&#176;" -- degree sign, U+00B0 ISOnum */,
464             "plusmn"
465             /* "&#177;" -- plus-minus sign = plus-or-minus sign, U+00B1 ISOnum */,
466             "sup2"
467             /* "&#178;" -- superscript two = superscript digit two = squared, U+00B2 ISOnum */,
468             "sup3"
469             /* "&#179;" -- superscript three = superscript digit three = cubed, U+00B3 ISOnum */,
470             "acute"
471             /* "&#180;" -- acute accent = spacing acute, U+00B4 ISOdia */,
472             "micro" /* "&#181;" -- micro sign, U+00B5 ISOnum */,
473             "para"
474             /* "&#182;" -- pilcrow sign = paragraph sign, U+00B6 ISOnum */,
475             "middot"
476             /* "&#183;" -- middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum */,
477             "cedil" /* "&#184;" -- cedilla = spacing cedilla, U+00B8 ISOdia */,
478             "sup1"
479             /* "&#185;" -- superscript one = superscript digit one, U+00B9 ISOnum */,
480             "ordm"
481             /* "&#186;" -- masculine ordinal indicator, U+00BA ISOnum */,
482             "raquo"
483             /* "&#187;" -- right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum */,
484             "frac14"
485             /* "&#188;" -- vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum --> */,
486             "frac12"
487             /* "&#189;" -- vulgar fraction one half = fraction one half, U+00BD ISOnum */,
488             "frac34"
489             /* "&#190;" -- vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum */,
490             "iquest"
491             /* "&#191;" -- inverted question mark = turned question mark, U+00BF ISOnum */,
492             "Agrave"
493             /* "&#192;" -- latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1 */,
494             "Aacute"
495             /* "&#193;" -- latin capital letter A with acute, U+00C1 ISOlat1 */,
496             "Acirc"
497             /* "&#194;" -- latin capital letter A with circumflex, U+00C2 ISOlat1 */,
498             "Atilde"
499             /* "&#195;" -- latin capital letter A with tilde, U+00C3 ISOlat1 */,
500             "Auml"
501             /* "&#196;" -- latin capital letter A with diaeresis, U+00C4 ISOlat1 */,
502             "Aring"
503             /* "&#197;" -- latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1 --> */,
504             "AElig"
505             /* "&#198;" -- latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1 --> */,
506             "Ccedil"
507             /* "&#199;" -- latin capital letter C with cedilla, U+00C7 ISOlat1 */,
508             "Egrave"
509             /* "&#200;" -- latin capital letter E with grave, U+00C8 ISOlat1 */,
510             "Eacute"
511             /* "&#201;" -- latin capital letter E with acute, U+00C9 ISOlat1 */,
512             "Ecirc"
513             /* "&#202;" -- latin capital letter E with circumflex, U+00CA ISOlat1 */,
514             "Euml"
515             /* "&#203;" -- latin capital letter E with diaeresis, U+00CB ISOlat1 */,
516             "Igrave"
517             /* "&#204;" -- latin capital letter I with grave, U+00CC ISOlat1 */,
518             "Iacute"
519             /* "&#205;" -- latin capital letter I with acute, U+00CD ISOlat1 */,
520             "Icirc"
521             /* "&#206;" -- latin capital letter I with circumflex, U+00CE ISOlat1 */,
522             "Iuml"
523             /* "&#207;" -- latin capital letter I with diaeresis, U+00CF ISOlat1 */,
524             "ETH" /* "&#208;" -- latin capital letter ETH, U+00D0 ISOlat1 */,
525             "Ntilde"
526             /* "&#209;" -- latin capital letter N with tilde, U+00D1 ISOlat1 */,
527             "Ograve"
528             /* "&#210;" -- latin capital letter O with grave, U+00D2 ISOlat1 */,
529             "Oacute"
530             /* "&#211;" -- latin capital letter O with acute, U+00D3 ISOlat1 */,
531             "Ocirc"
532             /* "&#212;" -- latin capital letter O with circumflex, U+00D4 ISOlat1 */,
533             "Otilde"
534             /* "&#213;" -- latin capital letter O with tilde, U+00D5 ISOlat1 */,
535             "Ouml"
536             /* "&#214;" -- latin capital letter O with diaeresis, U+00D6 ISOlat1 */,
537             "times" /* "&#215;" -- multiplication sign, U+00D7 ISOnum */,
538             "Oslash"
539             /* "&#216;" -- latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1 */,
540             "Ugrave"
541             /* "&#217;" -- latin capital letter U with grave, U+00D9 ISOlat1 */,
542             "Uacute"
543             /* "&#218;" -- latin capital letter U with acute, U+00DA ISOlat1 */,
544             "Ucirc"
545             /* "&#219;" -- latin capital letter U with circumflex, U+00DB ISOlat1 */,
546             "Uuml"
547             /* "&#220;" -- latin capital letter U with diaeresis, U+00DC ISOlat1 */,
548             "Yacute"
549             /* "&#221;" -- latin capital letter Y with acute, U+00DD ISOlat1 */,
550             "THORN"
551             /* "&#222;" -- latin capital letter THORN, U+00DE ISOlat1 */,
552             "szlig"
553             /* "&#223;" -- latin small letter sharp s = ess-zed, U+00DF ISOlat1 */,
554             "agrave"
555             /* "&#224;" -- latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1 */,
556             "aacute"
557             /* "&#225;" -- latin small letter a with acute, U+00E1 ISOlat1 */,
558             "acirc"
559             /* "&#226;" -- latin small letter a with circumflex, U+00E2 ISOlat1 */,
560             "atilde"
561             /* "&#227;" -- latin small letter a with tilde, U+00E3 ISOlat1 */,
562             "auml"
563             /* "&#228;" -- latin small letter a with diaeresis, U+00E4 ISOlat1 */,
564             "aring"
565             /* "&#229;" -- latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1 */,
566             "aelig"
567             /* "&#230;" -- latin small letter ae = latin small ligature ae, U+00E6 ISOlat1 */,
568             "ccedil"
569             /* "&#231;" -- latin small letter c with cedilla, U+00E7 ISOlat1 */,
570             "egrave"
571             /* "&#232;" -- latin small letter e with grave, U+00E8 ISOlat1 */,
572             "eacute"
573             /* "&#233;" -- latin small letter e with acute, U+00E9 ISOlat1 */,
574             "ecirc"
575             /* "&#234;" -- latin small letter e with circumflex, U+00EA ISOlat1 */,
576             "euml"
577             /* "&#235;" -- latin small letter e with diaeresis, U+00EB ISOlat1 */,
578             "igrave"
579             /* "&#236;" -- latin small letter i with grave, U+00EC ISOlat1 */,
580             "iacute"
581             /* "&#237;" -- latin small letter i with acute, U+00ED ISOlat1 */,
582             "icirc"
583             /* "&#238;" -- latin small letter i with circumflex, U+00EE ISOlat1 */,
584             "iuml"
585             /* "&#239;" -- latin small letter i with diaeresis, U+00EF ISOlat1 */,
586             "eth" /* "&#240;" -- latin small letter eth, U+00F0 ISOlat1 */,
587             "ntilde"
588             /* "&#241;" -- latin small letter n with tilde, U+00F1 ISOlat1 */,
589             "ograve"
590             /* "&#242;" -- latin small letter o with grave, U+00F2 ISOlat1 */,
591             "oacute"
592             /* "&#243;" -- latin small letter o with acute, U+00F3 ISOlat1 */,
593             "ocirc"
594             /* "&#244;" -- latin small letter o with circumflex, U+00F4 ISOlat1 */,
595             "otilde"
596             /* "&#245;" -- latin small letter o with tilde, U+00F5 ISOlat1 */,
597             "ouml"
598             /* "&#246;" -- latin small letter o with diaeresis, U+00F6 ISOlat1 */,
599             "divide" /* "&#247;" -- division sign, U+00F7 ISOnum */,
600             "oslash"
601             /* "&#248;" -- latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1 */,
602             "ugrave"
603             /* "&#249;" -- latin small letter u with grave, U+00F9 ISOlat1 */,
604             "uacute"
605             /* "&#250;" -- latin small letter u with acute, U+00FA ISOlat1 */,
606             "ucirc"
607             /* "&#251;" -- latin small letter u with circumflex, U+00FB ISOlat1 */,
608             "uuml"
609             /* "&#252;" -- latin small letter u with diaeresis, U+00FC ISOlat1 */,
610             "yacute"
611             /* "&#253;" -- latin small letter y with acute, U+00FD ISOlat1 */,
612             "thorn" /* "&#254;" -- latin small letter thorn,U+00FE ISOlat1 */,
613             "yuml"
614             /* "&#255;" -- latin small letter y with diaeresis, U+00FF ISOlat1 */,
615     };
616
617 }
618
Popular Tags