1 package org.codehaus.xfire.util;
2
3 import javax.xml.stream.XMLStreamConstants;
4 import javax.xml.stream.XMLStreamException;
5 import javax.xml.stream.XMLStreamReader;
6 import javax.xml.stream.XMLStreamWriter;
7
8 import org.w3c.dom.Attr;
9 import org.w3c.dom.Document;
10 import org.w3c.dom.Element;
11 import org.w3c.dom.NamedNodeMap;
12 import org.w3c.dom.Node;
13 import org.w3c.dom.NodeList;
14
15 /***
16 * Common StAX utilities.
17 *
18 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
19 * @since Oct 26, 2004
20 */
21 public class STAXUtils
22 {
23 /***
24 * Copies the reader to the writer. The start and end document
25 * methods must be handled on the writer manually.
26 *
27 * TODO: if the namespace on the reader has been declared previously
28 * to where we are in the stream, this probably won't work.
29 *
30 * @param reader
31 * @param writer
32 * @throws XMLStreamException
33 */
34 public static void copy( XMLStreamReader reader, XMLStreamWriter writer )
35 throws XMLStreamException
36 {
37 int read = 0;
38 int event = reader.getEventType();
39
40 while ( true )
41 {
42 switch( event )
43 {
44 case XMLStreamConstants.START_ELEMENT:
45 read++;
46 writeStartElement( reader, writer );
47 break;
48 case XMLStreamConstants.END_ELEMENT:
49 writer.writeEndElement();
50 read--;
51 if ( read <= 0 )
52 return;
53 break;
54 case XMLStreamConstants.CHARACTERS:
55 writer.writeCharacters( reader.getText() );
56 break;
57 case XMLStreamConstants.START_DOCUMENT:
58 case XMLStreamConstants.END_DOCUMENT:
59 case XMLStreamConstants.ATTRIBUTE:
60 case XMLStreamConstants.NAMESPACE:
61 break;
62 default:
63 break;
64 }
65 event = reader.next();
66 }
67 }
68
69 private static void writeStartElement(XMLStreamReader reader, XMLStreamWriter writer)
70 throws XMLStreamException
71 {
72 String local = reader.getLocalName();
73 String uri = reader.getNamespaceURI();
74 String prefix = reader.getPrefix();
75 if (prefix == null)
76 {
77 prefix = "";
78 }
79
80
81 if (uri != null)
82 {
83 if (prefix.length() == 0)
84 {
85 writer.writeStartElement(uri, local);
86 }
87 else
88 {
89 writer.writeStartElement(prefix, local, uri);
90 }
91 }
92 else
93 {
94 writer.writeStartElement( reader.getLocalName() );
95 }
96
97
98 for ( int i = 0; i < reader.getNamespaceCount(); i++ )
99 {
100 String nsPrefix = reader.getNamespacePrefix(i);
101 String nsURI = reader.getNamespaceURI(i);
102
103 if ( nsPrefix == null || nsPrefix.length() == 0 )
104 {
105 continue;
106 }
107
108 writer.writeNamespace(nsPrefix, nsURI);
109 }
110
111 String boundPrefix = writer.getPrefix(uri);
112 if ( boundPrefix == null || !prefix.equals(boundPrefix) )
113 {
114 if ( prefix.length() == 0)
115 writer.writeDefaultNamespace(uri);
116 else
117 writer.writeNamespace(prefix, uri);
118 }
119
120
121 for ( int i = 0; i < reader.getAttributeCount(); i++ )
122 {
123 String ns = reader.getAttributeNamespace(i);
124 if ( ns == null || ns.length() == 0 )
125 {
126 writer.writeAttribute(
127 reader.getAttributeLocalName(i),
128 reader.getAttributeValue(i));
129 }
130 else
131 {
132 writer.writeAttribute(
133 reader.getAttributeNamespace(i),
134 reader.getAttributeLocalName(i),
135 reader.getAttributeValue(i));
136 }
137 }
138 }
139
140 /***
141 * Writes an Element to an XMLStreamWriter. The writer must already
142 * have started the doucment (via writeStartDocument()). Also, this probably
143 * won't work with just a fragment of a document. The Element should be
144 * the root element of the document.
145 *
146 * @param e
147 * @param writer
148 * @throws XMLStreamException
149 */
150 public static void writeElement( Element e, XMLStreamWriter writer )
151 throws XMLStreamException
152 {
153 String prefix = e.getPrefix();
154 String ns = e.getNamespaceURI();
155 String localName = e.getLocalName();
156
157 if ( prefix == null )
158 {
159 if ( ns == null )
160 {
161 writer.writeStartElement( localName );
162 }
163 else
164 {
165 prefix = "";
166
167 writer.writeStartElement( ns, localName );
168
169 String curUri = writer.getNamespaceContext().getNamespaceURI(prefix);
170 if ( curUri == null || curUri.length() != ns.length() )
171 {
172 writer.writeDefaultNamespace(ns);
173 }
174 }
175 }
176 else
177 {
178 writer.writeStartElement(prefix, localName, ns);
179
180 String curUri = writer.getNamespaceContext().getNamespaceURI(prefix);
181 if ( curUri == null || curUri.length() != ns.length() || !curUri.equals(ns) )
182 {
183 System.out.println("writing namespace: " + ns);
184 writer.writeNamespace(prefix, ns);
185 }
186 }
187
188 NamedNodeMap attrs = e.getAttributes();
189 for ( int i = 0; i < attrs.getLength(); i++ )
190 {
191 Node attr = attrs.item(i);
192
193 boolean writeAttrNamespace = false;
194 String attrPrefix = writer.getNamespaceContext().getPrefix(attr.getNamespaceURI());
195 if ( attrPrefix == null )
196 {
197 writer.writeAttribute(attr.getNamespaceURI(), attr.getNodeName(), attr.getNodeValue());
198 }
199 else
200 {
201 writer.writeAttribute(attrPrefix, attr.getNamespaceURI(), attr.getNodeName(), attr.getNodeValue());
202 }
203 }
204
205 String value = DOMUtils.getContent(e);
206
207 if ( value != null && value.length() > 0)
208 writer.writeCharacters( value );
209
210 NodeList nodes = e.getChildNodes();
211 for ( int i = 0; i < nodes.getLength(); i++ )
212 {
213 Node n = nodes.item(i);
214 if ( n instanceof Element )
215 {
216 writeElement((Element)n, writer);
217 }
218 }
219
220 writer.writeEndElement();
221 }
222
223 /***
224 * @param e
225 * @return
226 */
227 private static Element getNamespaceDeclarer(Element e)
228 {
229 while( true )
230 {
231 Node n = e.getParentNode();
232 if ( n.equals(e) )
233 return null;
234 if ( n.getNamespaceURI() != null )
235 return (Element) n;
236 }
237 }
238
239 public static void readElements(Element root, XMLStreamReader reader)
240 throws XMLStreamException
241 {
242 int read = 0;
243
244 Document doc = root.getOwnerDocument();
245 Element e = null;
246
247 StringBuffer text = new StringBuffer();
248
249 while ( true )
250 {
251 int event = reader.next();
252 switch( event )
253 {
254 case XMLStreamConstants.START_ELEMENT:
255 read++;
256 e = doc.createElementNS(reader.getNamespaceURI(), reader.getLocalName());
257 root.appendChild(e);
258
259 for ( int i = 0; i < reader.getAttributeCount(); i++ )
260 {
261 Attr attr = doc.createAttributeNS(reader.getAttributeNamespace(i),
262 reader.getAttributeLocalName(i));
263 attr.setValue(reader.getAttributeValue(i));
264 e.setAttributeNode(attr);
265 }
266
267 readElements(e, reader);
268 break;
269 case XMLStreamConstants.END_ELEMENT:
270 DOMUtils.setText(root, text.toString());
271 return;
272 case XMLStreamConstants.CHARACTERS:
273 text.append(reader.getText());
274 break;
275 case XMLStreamConstants.END_DOCUMENT:
276 return;
277 case XMLStreamConstants.CDATA:
278 case XMLStreamConstants.START_DOCUMENT:
279 case XMLStreamConstants.ATTRIBUTE:
280 case XMLStreamConstants.NAMESPACE:
281 default:
282 break;
283 }
284 }
285 }
286 }