1 57 58 package org.jboss.axis.utils; 59 60 import org.w3c.dom.Attr ; 61 import org.w3c.dom.Element ; 62 import org.w3c.dom.NamedNodeMap ; 63 import org.w3c.dom.Node ; 64 import org.w3c.dom.NodeList ; 65 66 import java.io.PrintWriter ; 67 import java.io.StringWriter ; 68 import java.io.Writer ; 69 70 71 80 public class DOM2Writer 81 { 82 85 private static String NS_URI_XMLNS = "http://www.w3.org/2000/xmlns/"; 86 private static String NS_URI_XML = "http://www.w3.org/XML/1998/namespace"; 87 88 91 public static String nodeToString(Node node, boolean omitXMLDecl) 92 { 93 StringWriter sw = new StringWriter (); 94 95 serializeAsXML(node, sw, omitXMLDecl); 96 97 return sw.toString(); 98 } 99 100 103 public static void serializeAsXML(Node node, Writer writer, 104 boolean omitXMLDecl) 105 { 106 serializeAsXML(node, writer, omitXMLDecl, false, 0); 107 } 108 109 112 public static void serializeAsXML(Node node, Writer writer, 113 boolean omitXMLDecl, 114 boolean pretty, int indent) 115 { 116 PrintWriter out = new PrintWriter (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 node, NSStack namespaceStack, 125 PrintWriter 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 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 attrs = node.getAttributes(); 168 int len = (attrs != null) ? attrs.getLength() : 0; 169 170 for (int i = 0; i < len; i++) 171 { 172 Attr attr = (Attr )attrs.item(i); 173 174 String attrName = attr.getNodeName(); 175 String 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 attrPrefix = attr.getPrefix(); 184 String attrNamespaceURI = attr.getNamespaceURI(); 185 186 if (attrPrefix != null && attrNamespaceURI != null) 187 { 188 boolean prefixIsDeclared = false; 189 190 try 191 { 192 String namespaceURI = namespaceStack.getNamespaceURI(attrPrefix); 193 194 if (attrNamespaceURI.equals(namespaceURI)) 195 { 196 prefixIsDeclared = true; 197 } 198 } 199 catch (IllegalArgumentException e) 200 { 201 } 202 203 if (!prefixIsDeclared) 204 { 205 printNamespaceDecl(attr, namespaceStack, out); 206 } 207 } 208 } 209 210 String elPrefix = node.getPrefix(); 211 String 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 namespaceURI = namespaceStack.getNamespaceURI(elPrefix); 222 223 if (elNamespaceURI.equals(namespaceURI)) 224 { 225 prefixIsDeclared = true; 226 } 227 } 228 catch (IllegalArgumentException e) 229 { 230 } 231 232 if (!prefixIsDeclared) 233 { 234 printNamespaceDecl(node, namespaceStack, out); 235 } 236 } 237 238 NodeList 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 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 node, 346 NSStack namespaceStack, 347 PrintWriter out) 348 { 349 switch (node.getNodeType()) 350 { 351 case Node.ATTRIBUTE_NODE: 352 { 353 printNamespaceDecl(((Attr )node).getOwnerElement(), node, 354 namespaceStack, out); 355 break; 356 } 357 358 case Node.ELEMENT_NODE: 359 { 360 printNamespaceDecl((Element )node, node, namespaceStack, out); 361 break; 362 } 363 } 364 } 365 366 private static void printNamespaceDecl(Element owner, Node node, 367 NSStack namespaceStack, 368 PrintWriter out) 369 { 370 String namespaceURI = node.getNamespaceURI(); 371 String 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 normalize(String s) 391 { 392 StringBuffer str = new StringBuffer (); 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("<"); 404 break; 405 } 406 case '>': 407 { 408 str.append(">"); 409 break; 410 } 411 case '&': 412 { 413 str.append("&"); 414 break; 415 } 416 case '"': 417 { 418 str.append("""); 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 |