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