KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xml > XmlUtil


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.xml;
30
31 import com.caucho.util.CharBuffer;
32
33 import org.w3c.dom.Comment JavaDoc;
34 import org.w3c.dom.Document JavaDoc;
35 import org.w3c.dom.DocumentFragment JavaDoc;
36 import org.w3c.dom.Element JavaDoc;
37 import org.w3c.dom.Node JavaDoc;
38 import org.w3c.dom.ProcessingInstruction JavaDoc;
39 import org.xml.sax.ContentHandler JavaDoc;
40 import org.xml.sax.SAXException JavaDoc;
41
42 import java.io.IOException JavaDoc;
43 import java.util.HashMap JavaDoc;
44
45 /**
46  * XML utilities for manipulating names and the DOM.
47  */

48 public class XmlUtil {
49   /**
50    * Treats the string as an attribute list, splitting it into a HashMap.
51    *
52    * @param name a string to be interpreted as an attribute list
53    * @return a hash map containing the attribute (key, value) pairs.
54    */

55   public static HashMap JavaDoc<String JavaDoc,String JavaDoc> splitNameList(String JavaDoc name)
56     throws IOException JavaDoc
57   {
58     HashMap JavaDoc<String JavaDoc,String JavaDoc> attrs = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
59     CharBuffer cb = new CharBuffer();
60
61     int length = name.length();
62     int i = 0;
63     int ch = 0;
64     while (i < length) {
65       for (; i < length && XmlChar.isWhitespace(ch = name.charAt(i)); i++) {
66       }
67
68       if (i < length && ! XmlChar.isNameStart(ch))
69     throw new IOException JavaDoc("expected name at " + (char) ch);
70       
71       cb.clear();
72       while (i < length && XmlChar.isNameChar(ch)) {
73     cb.append((char) ch);
74
75     ch = name.charAt(++i);
76       }
77       String JavaDoc key = cb.toString();
78       cb.clear();
79
80       for (; i < length && XmlChar.isWhitespace(ch = name.charAt(i)); i++) {
81       }
82
83       if (ch != '=') {
84     attrs.put(key, "");
85     continue;
86       }
87
88       while (++i < length && XmlChar.isWhitespace(ch = name.charAt(i))) {
89       }
90
91       if (i >= length)
92     break;
93
94       cb.clear();
95       if (ch == '\'') {
96     while (++i < length && (ch = name.charAt(i)) != '\'')
97       cb.append((char) ch);
98     i++;
99       } else if (ch == '"') {
100     while (++i < length && (ch = name.charAt(i)) != '\"')
101       cb.append((char) ch);
102     i++;
103       } else if (XmlChar.isNameChar(ch)) {
104     cb.append((char) ch);
105     while (++i < length && XmlChar.isNameChar(ch = name.charAt(i)))
106       cb.append((char) ch);
107       } else
108     throw new IOException JavaDoc("unexpected");
109
110       attrs.put(key, cb.toString());
111     }
112
113     return attrs;
114   }
115
116   /**
117    * Extracts an attribute from a processing instruction. Since
118    * processing instructions are opaque, the standard DOM has no API
119    * for the common case where the PI value is an attribute list.
120    *
121    * <code><pre>
122    * &lt;?xml-stylesheet HREF="default.xsl"?&gt;
123    * </pre></code>
124    *
125    * <p>In the above example,
126    * <code><pre>getPIAttribute(node.getNodeValue(),&nbsp;"href")</pre></code>
127    * would return "default.xsl".
128    *
129    * @param pi the value of the processing instruction
130    * @param key the attribute key
131    * @return the value corresponding to the attribute key.
132    */

133   public static String JavaDoc getPIAttribute(String JavaDoc pi, String JavaDoc key)
134   {
135     CharBuffer nameBuf = new CharBuffer();
136     CharBuffer valueBuf = new CharBuffer();
137
138     int i = 0;
139     int length = pi.length();;
140     while (i < length) {
141       int ch = 0;
142       for (; i < length && XmlChar.isWhitespace(ch = pi.charAt(i)); i++) {
143       }
144
145       nameBuf.clear();
146       for (; i < length && XmlChar.isNameChar(ch = pi.charAt(i)); i++)
147     nameBuf.append((char) ch);
148
149       for (; i < length && XmlChar.isWhitespace(ch = pi.charAt(i)); i++) {
150       }
151       
152       if (i < length && ch != '=') {
153     if (nameBuf.length() == 0)
154       return null;
155     else if (nameBuf.toString().equals(key))
156       return nameBuf.toString();
157     else
158       continue;
159       }
160
161       i++;
162       for (; i < length && XmlChar.isWhitespace(ch = pi.charAt(i)); i++) {
163       }
164
165       // Parse the attribute value: '.*' or ".*" or \w+
166
valueBuf.clear();
167       if (ch == '\'') {
168     i++;
169     for (; i < length && (ch = pi.charAt(i)) != '\''; i++)
170       valueBuf.append((char) ch);
171     i++;
172       }
173       else if (ch == '\"') {
174     i++;
175     for (; i < length && (ch = pi.charAt(i)) != '\"'; i++)
176       valueBuf.append((char) ch);
177     i++;
178       }
179       else if (XmlChar.isNameChar(ch)) {
180     for (; i < length && XmlChar.isNameChar(ch = pi.charAt(i)); i++)
181       valueBuf.append((char) ch);
182       }
183       else
184     return null; // XXX: should throw an exception?
185

186       String JavaDoc name = nameBuf.toString();
187       if (name.equals(key))
188     return valueBuf.toString();
189     }
190
191     return null;
192   }
193
194   /**
195    * Get the next node in a depth first preorder traversal.
196    *
197    * <ul>
198    * <li>If the node has a child, return the child
199    * <li>Else if the node has a following sibling, return that sibling
200    * <li>Else if the node has a following uncle, return that uncle
201    * </ul>
202    *
203    * @param node the current node
204    * @return the next node in the preorder traversal
205    */

206   public static Node JavaDoc getNext(Node JavaDoc node)
207   {
208     if (node == null)
209       return null;
210     
211     if (node.getFirstChild() != null)
212       return node.getFirstChild();
213
214     for (; node != null; node = node.getParentNode()) {
215       if (node.getNextSibling() != null)
216     return node.getNextSibling();
217     }
218
219     return null;
220   }
221
222   /**
223    * Get the previous node in a DFS preorder traversal
224    *
225    * @param node the current node
226    * @return the previous node in the preorder traversal
227    */

228   public static Node JavaDoc getPrevious(Node JavaDoc node)
229   {
230     Node JavaDoc previous;
231
232     if (node == null)
233       return null;
234
235     if ((previous = node.getPreviousSibling()) != null) {
236       for (;
237        previous.getLastChild() != null;
238        previous = previous.getLastChild()) {
239       }
240
241       return previous;
242     }
243
244     return node.getParentNode();
245   }
246
247   /**
248    * Extracts the text value from the node. Text nodes return their
249    * value and elements return the concatenation of the child values.
250    */

251   public static String JavaDoc textValue(Node JavaDoc node)
252   {
253     if (node instanceof Element JavaDoc || node instanceof DocumentFragment JavaDoc) {
254       String JavaDoc s = null;
255       CharBuffer cb = null;
256       
257       for (Node JavaDoc child = node.getFirstChild();
258            child != null;
259            child = child.getNextSibling()) {
260         String JavaDoc value = null;
261         
262         if (child instanceof Element JavaDoc || child instanceof Document JavaDoc) {
263           if (cb == null)
264             cb = new CharBuffer();
265           if (s != null)
266             cb.append(s);
267           s = null;
268
269           textValue(cb, child);
270         }
271         else if ((value = child.getNodeValue()) == null || value == "") {
272         }
273         else if (cb != null)
274           cb.append(value);
275         else if (s == null && s != "") {
276           s = value;
277         }
278         else {
279           cb = new CharBuffer();
280
281           cb.append(s);
282           cb.append(value);
283           s = null;
284         }
285       }
286
287       if (s != null)
288         return s;
289       else if (cb != null)
290         return cb.toString();
291       else
292         return "";
293     }
294     else {
295       String JavaDoc value = node.getNodeValue();
296
297       if (value != null)
298     return value;
299       else
300     return "";
301     }
302   }
303
304   /**
305    * Extracts the text value from the node. Text nodes return their
306    * value and elements return the concatenation of the child values.
307    */

308   public static void textValue(CharBuffer cb, Node JavaDoc node)
309   {
310     if (node instanceof Element JavaDoc || node instanceof DocumentFragment JavaDoc) {
311       for (Node JavaDoc child = node.getFirstChild();
312            child != null;
313            child = child.getNextSibling()) {
314         textValue(cb, child);
315       }
316     }
317     else if (node instanceof Comment JavaDoc || node instanceof ProcessingInstruction JavaDoc) {
318     }
319     else
320       cb.append(node.getNodeValue());
321   }
322
323   /**
324    * Extracts the text value from the node. Text nodes return their
325    * value and elements return the concatenation of the child values.
326    */

327   public static boolean isWhitespace(String JavaDoc text)
328   {
329     for (int i = text.length() - 1; i >= 0; i--)
330       if (! XmlChar.isWhitespace(text.charAt(i)))
331     return false;
332
333     return true;
334   }
335
336   /**
337    * Sends data to the helper.
338    */

339   public static void toSAX(Node JavaDoc node, ContentHandler JavaDoc handler)
340     throws SAXException JavaDoc
341   {
342     for (; node != null; node = node.getNextSibling()) {
343       if (node instanceof ProcessingInstruction JavaDoc) {
344         ProcessingInstruction JavaDoc pi = (ProcessingInstruction JavaDoc) node;
345
346         handler.processingInstruction(pi.getNodeName(), pi.getData());
347       }
348       else if (node instanceof DocumentFragment JavaDoc) {
349         toSAX(node.getFirstChild(), handler);
350       }
351     }
352   }
353
354   /**
355    * Returns the namespace for the given prefix.
356    */

357   public static String JavaDoc getNamespace(Node JavaDoc node, String JavaDoc prefix)
358   {
359     for (; node != null; node = node.getParentNode()) {
360       if (node instanceof CauchoElement)
361     return ((CauchoElement) node).getNamespace(prefix);
362     }
363
364     return null;
365   }
366 }
367
Popular Tags