1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.common.util;
21
22 import org.w3c.dom.Attr;
23 import org.w3c.dom.Element;
24 import org.w3c.dom.NamedNodeMap;
25 import org.w3c.dom.Node;
26
27 import java.io.PrintWriter;
28 import java.io.StringWriter;
29 import java.io.Writer;
30
31
32
33
34
35
36
37 public final class DOM2Writer {
38 public static final char NL = '\n';
39 public static final String LS = System.getProperty("line.separator",
40 Character.valueOf(NL).toString());
41
42 private DOM2Writer() {
43
44 }
45
46
47
48
49 public static String nodeToString(Node node) {
50 StringWriter sw = new StringWriter();
51 serializeAsXML(node, sw, true);
52 return sw.toString();
53 }
54
55
56
57
58 public static String nodeToString(Node node, boolean omitXMLDecl) {
59 StringWriter sw = new StringWriter();
60 serializeAsXML(node, sw, omitXMLDecl);
61 return sw.toString();
62 }
63
64
65
66
67 public static void serializeAsXML(Node node, Writer writer,
68 boolean omitXMLDecl) {
69 serializeAsXML(node, writer, omitXMLDecl, false);
70 }
71
72
73
74
75 public static void serializeAsXML(Node node, Writer writer,
76 boolean omitXMLDecl,
77 boolean pretty) {
78 PrintWriter out = new PrintWriter(writer);
79 if (!omitXMLDecl) {
80 out.print("<?xml version=\"1.0\" encoding=UTF-8 ?>");
81 }
82 NSStack namespaceStack = new NSStack();
83 print(node, namespaceStack, out, pretty, 0);
84 out.flush();
85 }
86
87 private static void print(Node node, NSStack namespaceStack,
88 PrintWriter out, boolean pretty,
89 int indent) {
90 if (node == null) {
91 return;
92 }
93 boolean hasChildren = false;
94 int type = node.getNodeType();
95 switch (type) {
96 case Node.DOCUMENT_NODE:
97 Node child = node.getFirstChild();
98 while (child != null) {
99 print(child, namespaceStack, out, pretty, indent);
100 child = child.getNextSibling();
101 }
102 break;
103 case Node.ELEMENT_NODE:
104 namespaceStack.push();
105 if (pretty) {
106 for (int i = 0; i < indent; i++) {
107 out.print(' ');
108 }
109 }
110 out.print('<' + node.getNodeName());
111 String elPrefix = node.getPrefix();
112 String elNamespaceURI = node.getNamespaceURI();
113 if (elPrefix != null && elNamespaceURI != null && elPrefix.length() > 0) {
114 boolean prefixIsDeclared = false;
115 try {
116 String namespaceURI = namespaceStack.getNamespaceURI(elPrefix);
117 if (elNamespaceURI.equals(namespaceURI)) {
118 prefixIsDeclared = true;
119 }
120 } catch (IllegalArgumentException e) {
121
122 }
123 if (!prefixIsDeclared) {
124 printNamespaceDecl(node, namespaceStack, out);
125 }
126 }
127 NamedNodeMap attrs = node.getAttributes();
128 int len = (attrs != null) ? attrs.getLength() : 0;
129 for (int i = 0; i < len; i++) {
130 Attr attr = (Attr) attrs.item(i);
131 out.print(' ' + attr.getNodeName() + "=\"");
132 normalize(attr.getValue(), out);
133 out.print('\"');
134 String attrPrefix = attr.getPrefix();
135 String attrNamespaceURI = attr.getNamespaceURI();
136 if (attrPrefix != null && attrNamespaceURI != null) {
137 boolean prefixIsDeclared = false;
138 try {
139 String namespaceURI = namespaceStack.getNamespaceURI(attrPrefix);
140 if (attrNamespaceURI.equals(namespaceURI)) {
141 prefixIsDeclared = true;
142 }
143 } catch (IllegalArgumentException e) {
144
145 }
146 if (!prefixIsDeclared) {
147 printNamespaceDecl(attr, namespaceStack, out);
148 }
149 }
150 }
151 child = node.getFirstChild();
152 if (child != null) {
153 hasChildren = true;
154 out.print('>');
155 if (pretty) {
156 out.print(LS);
157 }
158 while (child != null) {
159 print(child, namespaceStack, out, pretty, indent + 1);
160 child = child.getNextSibling();
161 }
162 } else {
163 hasChildren = false;
164 out.print("/>");
165 if (pretty) {
166 out.print(LS);
167 }
168 }
169 namespaceStack.pop();
170 break;
171 case Node.ENTITY_REFERENCE_NODE:
172 out.print('&');
173 out.print(node.getNodeName());
174 out.print(';');
175 break;
176 case Node.CDATA_SECTION_NODE:
177 out.print("<![CDATA[");
178 out.print(node.getNodeValue());
179 out.print("]]>");
180 break;
181 case Node.TEXT_NODE:
182 normalize(node.getNodeValue(), out);
183 break;
184 case Node.COMMENT_NODE:
185 out.print("<!--");
186 out.print(node.getNodeValue());
187 out.print("-->");
188 if (pretty) {
189 out.print(LS);
190 }
191 break;
192 case Node.PROCESSING_INSTRUCTION_NODE:
193 out.print("<?");
194 out.print(node.getNodeName());
195 String data = node.getNodeValue();
196 if (data != null && data.length() > 0) {
197 out.print(' ');
198 out.print(data);
199 }
200 out.println("?>");
201 if (pretty) {
202 out.print(LS);
203 }
204 break;
205 }
206 if (type == Node.ELEMENT_NODE && hasChildren) {
207 if (pretty) {
208 for (int i = 0; i < indent; i++) {
209 out.print(' ');
210 }
211 }
212 out.print("</");
213 out.print(node.getNodeName());
214 out.print('>');
215 if (pretty) {
216 out.print(LS);
217 }
218 hasChildren = false;
219 }
220 }
221
222 private static void printNamespaceDecl(Node node,
223 NSStack namespaceStack,
224 PrintWriter out) {
225 switch (node.getNodeType()) {
226 case Node.ATTRIBUTE_NODE:
227 printNamespaceDecl(((Attr) node).getOwnerElement(), node,
228 namespaceStack, out);
229 break;
230 case Node.ELEMENT_NODE:
231 printNamespaceDecl((Element) node, node, namespaceStack, out);
232 break;
233 }
234 }
235
236 private static void printNamespaceDecl(Element owner, Node node,
237 NSStack namespaceStack,
238 PrintWriter out) {
239 String namespaceURI = node.getNamespaceURI();
240 String prefix = node.getPrefix();
241 if (!(namespaceURI.equals(XMLUtils.XMLNS_NS) && "xmlns".equals(prefix))
242 && !(namespaceURI.equals(XMLUtils.XML_NS) && "xml".equals(prefix))) {
243 if (XMLUtils.getNamespace(prefix, owner) == null) {
244 out.print(" xmlns:" + prefix + "=\"" + namespaceURI + '\"');
245 }
246 } else {
247 prefix = node.getLocalName();
248 namespaceURI = node.getNodeValue();
249 }
250 namespaceStack.add(namespaceURI, prefix);
251 }
252
253
254
255
256 public static void normalize(String s, PrintWriter fOut) {
257 int len = (s != null) ? s.length() : 0;
258 for (int i = 0; i < len; i++) {
259 char c = s.charAt(i);
260 switch (c) {
261 case '<':
262 fOut.print("<");
263 break;
264 case '>':
265 fOut.print(">");
266 break;
267 case '&':
268 fOut.print("&");
269 break;
270 case '"':
271 fOut.print(""");
272 break;
273 default:
274 fOut.print(c);
275 break;
276 }
277 }
278 }
279 }