KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > utils > DOM2Writer


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "SOAP" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 2000, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.jboss.axis.utils;
59
60 import org.w3c.dom.Attr JavaDoc;
61 import org.w3c.dom.Element JavaDoc;
62 import org.w3c.dom.NamedNodeMap JavaDoc;
63 import org.w3c.dom.Node JavaDoc;
64 import org.w3c.dom.NodeList JavaDoc;
65
66 import java.io.PrintWriter JavaDoc;
67 import java.io.StringWriter JavaDoc;
68 import java.io.Writer JavaDoc;
69
70
71 /**
72  * This class is a utility to serialize a DOM node as XML. This class
73  * uses the <code>DOM Level 2</code> APIs.
74  * The main difference between this class and DOMWriter is that this class
75  * generates and prints out namespace declarations.
76  *
77  * @author Matthew J. Duftler (duftler@us.ibm.com)
78  * @author Joseph Kesselman
79  */

80 public class DOM2Writer
81 {
82    /**
83     * The namespaceURI represented by the prefix <code>xmlns</code>.
84     */

85    private static String JavaDoc NS_URI_XMLNS = "http://www.w3.org/2000/xmlns/";
86    private static String JavaDoc NS_URI_XML = "http://www.w3.org/XML/1998/namespace";
87
88    /**
89     * Return a string containing this node serialized as XML.
90     */

91    public static String JavaDoc nodeToString(Node JavaDoc node, boolean omitXMLDecl)
92    {
93       StringWriter JavaDoc sw = new StringWriter JavaDoc();
94
95       serializeAsXML(node, sw, omitXMLDecl);
96
97       return sw.toString();
98    }
99
100    /**
101     * Serialize this node into the writer as XML.
102     */

103    public static void serializeAsXML(Node JavaDoc node, Writer JavaDoc writer,
104                                      boolean omitXMLDecl)
105    {
106       serializeAsXML(node, writer, omitXMLDecl, false, 0);
107    }
108
109    /**
110     * Serialize this node into the writer as XML.
111     */

112    public static void serializeAsXML(Node JavaDoc node, Writer JavaDoc writer,
113                                      boolean omitXMLDecl,
114                                      boolean pretty, int indent)
115    {
116       PrintWriter JavaDoc out = new PrintWriter JavaDoc(writer);
117       if (!omitXMLDecl)
118          out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
119       NSStack namespaceStack = new NSStack();
120       print(node, namespaceStack, out, pretty, indent);
121       out.flush();
122    }
123
124    private static void print(Node JavaDoc node, NSStack namespaceStack,
125                              PrintWriter JavaDoc out, boolean pretty,
126                              int indent)
127    {
128       if (node == null)
129       {
130          return;
131       }
132
133       boolean hasChildren = false;
134       int type = node.getNodeType();
135
136       switch (type)
137       {
138          case Node.DOCUMENT_NODE:
139             {
140                NodeList JavaDoc children = node.getChildNodes();
141
142                if (children != null)
143                {
144                   int numChildren = children.getLength();
145
146                   for (int i = 0; i < numChildren; i++)
147                   {
148                      print(children.item(i), namespaceStack, out,
149                              pretty, indent);
150                   }
151                }
152                break;
153             }
154
155          case Node.ELEMENT_NODE:
156             {
157                namespaceStack.push();
158
159                if (pretty)
160                {
161                   for (int i = 0; i < indent; i++)
162                      out.print(' ');
163                }
164
165                out.print('<' + node.getNodeName());
166
167                NamedNodeMap JavaDoc attrs = node.getAttributes();
168                int len = (attrs != null) ? attrs.getLength() : 0;
169
170                for (int i = 0; i < len; i++)
171                {
172                   Attr JavaDoc attr = (Attr JavaDoc)attrs.item(i);
173
174                   String JavaDoc attrName = attr.getNodeName();
175                   String JavaDoc attrValue = attr.getValue();
176                   out.print(' ' + attrName + "=\"" + normalize(attrValue) + '\"');
177
178                   if (attrName.startsWith("xmlns:"))
179                   {
180                      namespaceStack.add(attrValue, attrName.substring(6));
181                   }
182
183                   String JavaDoc attrPrefix = attr.getPrefix();
184                   String JavaDoc attrNamespaceURI = attr.getNamespaceURI();
185
186                   if (attrPrefix != null && attrNamespaceURI != null)
187                   {
188                      boolean prefixIsDeclared = false;
189
190                      try
191                      {
192                         String JavaDoc namespaceURI = namespaceStack.getNamespaceURI(attrPrefix);
193
194                         if (attrNamespaceURI.equals(namespaceURI))
195                         {
196                            prefixIsDeclared = true;
197                         }
198                      }
199                      catch (IllegalArgumentException JavaDoc e)
200                      {
201                      }
202
203                      if (!prefixIsDeclared)
204                      {
205                         printNamespaceDecl(attr, namespaceStack, out);
206                      }
207                   }
208                }
209
210                String JavaDoc elPrefix = node.getPrefix();
211                String JavaDoc elNamespaceURI = node.getNamespaceURI();
212
213                if (elPrefix != null &&
214                        elNamespaceURI != null &&
215                        elPrefix.length() > 0)
216                {
217                   boolean prefixIsDeclared = false;
218
219                   try
220                   {
221                      String JavaDoc namespaceURI = namespaceStack.getNamespaceURI(elPrefix);
222
223                      if (elNamespaceURI.equals(namespaceURI))
224                      {
225                         prefixIsDeclared = true;
226                      }
227                   }
228                   catch (IllegalArgumentException JavaDoc e)
229                   {
230                   }
231
232                   if (!prefixIsDeclared)
233                   {
234                      printNamespaceDecl(node, namespaceStack, out);
235                   }
236                }
237
238                NodeList JavaDoc children = node.getChildNodes();
239
240                if (children != null)
241                {
242                   int numChildren = children.getLength();
243
244                   hasChildren = (numChildren > 0);
245
246                   if (hasChildren)
247                   {
248                      if (pretty)
249                         out.println('>');
250                      else
251                         out.print('>');
252                   }
253
254                   for (int i = 0; i < numChildren; i++)
255                   {
256                      print(children.item(i), namespaceStack, out, pretty,
257                              indent + 1);
258                   }
259                }
260                else
261                {
262                   hasChildren = false;
263                }
264
265                if (!hasChildren)
266                {
267                   if (pretty)
268                      out.println("/>");
269                   else
270                      out.print("/>");
271                }
272
273                namespaceStack.pop();
274                break;
275             }
276
277          case Node.ENTITY_REFERENCE_NODE:
278             {
279                out.print('&');
280                out.print(node.getNodeName());
281                out.print(';');
282                break;
283             }
284
285          case Node.CDATA_SECTION_NODE:
286             {
287                out.print("<![CDATA[");
288                out.print(node.getNodeValue());
289                out.print("]]>");
290                break;
291             }
292
293          case Node.TEXT_NODE:
294             {
295                out.print(normalize(node.getNodeValue()));
296                break;
297             }
298
299          case Node.COMMENT_NODE:
300             {
301                out.print("<!--");
302                out.print(node.getNodeValue());
303                out.print("-->");
304                if (pretty)
305                   out.print(JavaUtils.LS);
306                break;
307             }
308
309          case Node.PROCESSING_INSTRUCTION_NODE:
310             {
311                out.print("<?");
312                out.print(node.getNodeName());
313
314                String JavaDoc data = node.getNodeValue();
315
316                if (data != null && data.length() > 0)
317                {
318                   out.print(' ');
319                   out.print(data);
320                }
321
322                out.println("?>");
323                if (pretty)
324                   out.print(JavaUtils.LS);
325                break;
326             }
327       }
328
329       if (type == Node.ELEMENT_NODE && hasChildren == true)
330       {
331          if (pretty)
332          {
333             for (int i = 0; i < indent; i++)
334                out.print(' ');
335          }
336          out.print("</");
337          out.print(node.getNodeName());
338          out.print('>');
339          if (pretty)
340             out.print(JavaUtils.LS);
341          hasChildren = false;
342       }
343    }
344
345    private static void printNamespaceDecl(Node JavaDoc node,
346                                           NSStack namespaceStack,
347                                           PrintWriter JavaDoc out)
348    {
349       switch (node.getNodeType())
350       {
351          case Node.ATTRIBUTE_NODE:
352             {
353                printNamespaceDecl(((Attr JavaDoc)node).getOwnerElement(), node,
354                        namespaceStack, out);
355                break;
356             }
357
358          case Node.ELEMENT_NODE:
359             {
360                printNamespaceDecl((Element JavaDoc)node, node, namespaceStack, out);
361                break;
362             }
363       }
364    }
365
366    private static void printNamespaceDecl(Element JavaDoc owner, Node JavaDoc node,
367                                           NSStack namespaceStack,
368                                           PrintWriter JavaDoc out)
369    {
370       String JavaDoc namespaceURI = node.getNamespaceURI();
371       String JavaDoc prefix = node.getPrefix();
372
373       if (!(namespaceURI.equals(NS_URI_XMLNS) && prefix.equals("xmlns")) &&
374               !(namespaceURI.equals(NS_URI_XML) && prefix.equals("xml")))
375       {
376          if (XMLUtils.getNamespace(prefix, owner) == null)
377          {
378             out.print(" xmlns:" + prefix + "=\"" + namespaceURI + '\"');
379          }
380       }
381       else
382       {
383          prefix = node.getLocalName();
384          namespaceURI = node.getNodeValue();
385       }
386
387       namespaceStack.add(namespaceURI, prefix);
388    }
389
390    public static String JavaDoc normalize(String JavaDoc s)
391    {
392       StringBuffer JavaDoc str = new StringBuffer JavaDoc();
393       int len = (s != null) ? s.length() : 0;
394
395       for (int i = 0; i < len; i++)
396       {
397          char ch = s.charAt(i);
398
399          switch (ch)
400          {
401             case '<':
402                {
403                   str.append("&lt;");
404                   break;
405                }
406             case '>':
407                {
408                   str.append("&gt;");
409                   break;
410                }
411             case '&':
412                {
413                   str.append("&amp;");
414                   break;
415                }
416             case '"':
417                {
418                   str.append("&quot;");
419                   break;
420                }
421             case JavaUtils.NL:
422                {
423                   if (i > 0)
424                   {
425                      char lastChar = str.charAt(str.length() - 1);
426
427                      if (lastChar != JavaUtils.CR)
428                      {
429                         str.append(JavaUtils.LS);
430                      }
431                      else
432                      {
433                         str.append(JavaUtils.NL);
434                      }
435                   }
436                   else
437                   {
438                      str.append(JavaUtils.LS);
439                   }
440                   break;
441                }
442             default :
443                {
444                   str.append(ch);
445                }
446          }
447       }
448
449       return (str.toString());
450    }
451 }
452
Popular Tags