View Javadoc

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; // number of elements read in
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          // Write out the element name and possible the default namespace
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          // Write out the namespaces
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         // Write out attributes
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; // number of elements read in
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 }