001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.staxutils;
019:
020: import java.io.InputStream;
021: import java.io.OutputStream;
022: import java.io.Reader;
023: import java.io.Writer; //import java.util.HashMap;
024: //import java.util.Map;
025: import java.util.logging.Logger;
026:
027: import javax.xml.namespace.NamespaceContext;
028: import javax.xml.namespace.QName;
029: import javax.xml.parsers.DocumentBuilder;
030: import javax.xml.stream.StreamFilter;
031: import javax.xml.stream.XMLInputFactory;
032: import javax.xml.stream.XMLOutputFactory;
033: import javax.xml.stream.XMLStreamConstants;
034: import javax.xml.stream.XMLStreamException;
035: import javax.xml.stream.XMLStreamReader;
036: import javax.xml.stream.XMLStreamWriter;
037: import javax.xml.transform.Result;
038: import javax.xml.transform.Source;
039: import javax.xml.transform.dom.DOMSource;
040:
041: import org.w3c.dom.Attr;
042: import org.w3c.dom.CDATASection;
043: import org.w3c.dom.Comment;
044: import org.w3c.dom.Document;
045: import org.w3c.dom.Element;
046: import org.w3c.dom.EntityReference;
047: import org.w3c.dom.NamedNodeMap;
048: import org.w3c.dom.Node;
049: import org.w3c.dom.NodeList;
050: import org.w3c.dom.ProcessingInstruction;
051: import org.w3c.dom.Text;
052:
053: import org.apache.cxf.common.util.StringUtils;
054: import org.apache.cxf.helpers.DOMUtils;
055: import org.apache.cxf.helpers.XMLUtils;
056:
057: public final class StaxUtils {
058:
059: private static final Logger LOG = Logger.getLogger(StaxUtils.class
060: .getName());
061:
062: private static final XMLInputFactory XML_NS_AWARE_INPUT_FACTORY = XMLInputFactory
063: .newInstance();
064: private static final XMLInputFactory XML_INPUT_FACTORY = XMLInputFactory
065: .newInstance();
066: private static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory
067: .newInstance();
068:
069: private static final String XML_NS = "http://www.w3.org/2000/xmlns/";
070:
071: static {
072: XML_INPUT_FACTORY.setProperty(
073: XMLInputFactory.IS_NAMESPACE_AWARE, false);
074: XML_NS_AWARE_INPUT_FACTORY.setProperty(
075: XMLInputFactory.IS_NAMESPACE_AWARE, true);
076: }
077:
078: private StaxUtils() {
079: }
080:
081: public static XMLInputFactory getXMLInputFactory() {
082: return getXMLInputFactory(true);
083: }
084:
085: public static XMLInputFactory getXMLInputFactory(boolean nsAware) {
086: return nsAware ? XML_NS_AWARE_INPUT_FACTORY : XML_INPUT_FACTORY;
087: }
088:
089: public static XMLOutputFactory getXMLOutputFactory() {
090: return XML_OUTPUT_FACTORY;
091: }
092:
093: public static XMLStreamWriter createXMLStreamWriter(Writer out) {
094: try {
095: return getXMLOutputFactory().createXMLStreamWriter(out);
096: } catch (XMLStreamException e) {
097: throw new RuntimeException("Cant' create XMLStreamWriter",
098: e);
099: }
100: }
101:
102: public static XMLStreamWriter createXMLStreamWriter(OutputStream out) {
103: return createXMLStreamWriter(out, null);
104: }
105:
106: public static XMLStreamWriter createXMLStreamWriter(
107: OutputStream out, String encoding) {
108: if (encoding == null) {
109: encoding = "UTF-8";
110: }
111:
112: try {
113: return getXMLOutputFactory().createXMLStreamWriter(out,
114: encoding);
115: } catch (XMLStreamException e) {
116: throw new RuntimeException("Cant' create XMLStreamWriter",
117: e);
118: }
119: }
120:
121: public static XMLStreamWriter createXMLStreamWriter(Result r) {
122: try {
123: return getXMLOutputFactory().createXMLStreamWriter(r);
124: } catch (XMLStreamException e) {
125: throw new RuntimeException("Cant' create XMLStreamWriter",
126: e);
127: }
128: }
129:
130: public static XMLStreamReader createFilteredReader(
131: XMLStreamReader reader, StreamFilter filter) {
132: try {
133: return getXMLInputFactory().createFilteredReader(reader,
134: filter);
135: } catch (XMLStreamException e) {
136: throw new RuntimeException("Cant' create XMLStreamReader",
137: e);
138: }
139: }
140:
141: public static void nextEvent(XMLStreamReader dr) {
142: try {
143: dr.next();
144: } catch (XMLStreamException e) {
145: throw new RuntimeException("Couldn't parse stream.", e);
146: }
147: }
148:
149: public static boolean toNextText(DepthXMLStreamReader reader) {
150: if (reader.getEventType() == XMLStreamReader.CHARACTERS) {
151: return true;
152: }
153:
154: try {
155: int depth = reader.getDepth();
156: int event = reader.getEventType();
157: while (reader.getDepth() >= depth && reader.hasNext()) {
158: if (event == XMLStreamReader.CHARACTERS
159: && reader.getDepth() == depth + 1) {
160: return true;
161: }
162: event = reader.next();
163: }
164: return false;
165: } catch (XMLStreamException e) {
166: throw new RuntimeException("Couldn't parse stream.", e);
167: }
168: }
169:
170: public static boolean toNextTag(DepthXMLStreamReader reader,
171: QName endTag) {
172: try {
173: int depth = reader.getDepth();
174: int event = reader.getEventType();
175: while (reader.getDepth() >= depth && reader.hasNext()) {
176: if (event == XMLStreamReader.START_ELEMENT
177: && reader.getName().equals(endTag)
178: && reader.getDepth() == depth + 1) {
179: return true;
180: }
181: event = reader.next();
182: }
183: return false;
184: } catch (XMLStreamException e) {
185: throw new RuntimeException("Couldn't parse stream.", e);
186: }
187: }
188:
189: public static void writeStartElement(XMLStreamWriter writer,
190: String prefix, String name, String namespace)
191: throws XMLStreamException {
192: if (prefix == null) {
193: prefix = "";
194: }
195:
196: if (namespace.length() > 0) {
197: writer.writeStartElement(prefix, name, namespace);
198: writer.writeNamespace(prefix, namespace);
199: } else {
200: writer.writeStartElement(name);
201: writer.writeDefaultNamespace("");
202: }
203: }
204:
205: /**
206: * Returns true if currently at the start of an element, otherwise move
207: * forwards to the next element start and return true, otherwise false is
208: * returned if the end of the stream is reached.
209: */
210: public static boolean skipToStartOfElement(XMLStreamReader in)
211: throws XMLStreamException {
212: for (int code = in.getEventType(); code != XMLStreamReader.END_DOCUMENT; code = in
213: .next()) {
214: if (code == XMLStreamReader.START_ELEMENT) {
215: return true;
216: }
217: }
218: return false;
219: }
220:
221: public static boolean toNextElement(DepthXMLStreamReader dr) {
222: if (dr.getEventType() == XMLStreamReader.START_ELEMENT) {
223: return true;
224: }
225: if (dr.getEventType() == XMLStreamReader.END_ELEMENT) {
226: return false;
227: }
228: try {
229: int depth = dr.getDepth();
230:
231: for (int event = dr.getEventType(); dr.getDepth() >= depth
232: && dr.hasNext(); event = dr.next()) {
233: if (event == XMLStreamReader.START_ELEMENT
234: && dr.getDepth() == depth + 1) {
235: return true;
236: } else if (event == XMLStreamReader.END_ELEMENT) {
237: depth--;
238: }
239: }
240:
241: return false;
242: } catch (XMLStreamException e) {
243: throw new RuntimeException("Couldn't parse stream.", e);
244: }
245: }
246:
247: public static boolean skipToStartOfElement(DepthXMLStreamReader in)
248: throws XMLStreamException {
249: for (int code = in.getEventType(); code != XMLStreamReader.END_DOCUMENT; code = in
250: .next()) {
251: if (code == XMLStreamReader.START_ELEMENT) {
252: return true;
253: }
254: }
255: return false;
256: }
257:
258: public static void copy(Document doc, XMLStreamWriter writer)
259: throws XMLStreamException {
260: XMLStreamReader reader = createXMLStreamReader(doc);
261: copy(reader, writer);
262: }
263:
264: public static void copy(Element node, XMLStreamWriter writer)
265: throws XMLStreamException {
266: XMLStreamReader reader = createXMLStreamReader(node);
267: copy(reader, writer);
268: }
269:
270: /**
271: * Copies the reader to the writer. The start and end document methods must
272: * be handled on the writer manually. TODO: if the namespace on the reader
273: * has been declared previously to where we are in the stream, this probably
274: * won't work.
275: *
276: * @param reader
277: * @param writer
278: * @throws XMLStreamException
279: */
280: public static void copy(XMLStreamReader reader,
281: XMLStreamWriter writer) throws XMLStreamException {
282: // number of elements read in
283: int read = 0;
284: int event = reader.getEventType();
285:
286: while (reader.hasNext()) {
287: switch (event) {
288: case XMLStreamConstants.START_ELEMENT:
289: read++;
290: writeStartElement(reader, writer);
291: break;
292: case XMLStreamConstants.END_ELEMENT:
293: writer.writeEndElement();
294: read--;
295: if (read <= 0) {
296: return;
297: }
298: break;
299: case XMLStreamConstants.CHARACTERS:
300: writer.writeCharacters(reader.getText());
301: break;
302: case XMLStreamConstants.START_DOCUMENT:
303: case XMLStreamConstants.END_DOCUMENT:
304: case XMLStreamConstants.ATTRIBUTE:
305: case XMLStreamConstants.NAMESPACE:
306: break;
307: default:
308: break;
309: }
310: event = reader.next();
311: }
312: }
313:
314: private static void writeStartElement(XMLStreamReader reader,
315: XMLStreamWriter writer) throws XMLStreamException {
316: String local = reader.getLocalName();
317: String uri = reader.getNamespaceURI();
318: String prefix = reader.getPrefix();
319: if (prefix == null) {
320: prefix = "";
321: }
322:
323: // System.out.println("STAXUTILS:writeStartElement : node name : " + local + " namespace URI" + uri);
324: boolean writeElementNS = false;
325: if (uri != null) {
326: String boundPrefix = writer.getPrefix(uri);
327: if (boundPrefix == null || !prefix.equals(boundPrefix)) {
328: writeElementNS = true;
329: }
330: }
331:
332: // Write out the element name
333: if (uri != null) {
334: if (prefix.length() == 0 && StringUtils.isEmpty(uri)) {
335: writer.writeStartElement(local);
336: writer.setDefaultNamespace(uri);
337:
338: } else {
339: writer.writeStartElement(prefix, local, uri);
340: writer.setPrefix(prefix, uri);
341: }
342: } else {
343: writer.writeStartElement(local);
344: }
345:
346: // Write out the namespaces
347: for (int i = 0; i < reader.getNamespaceCount(); i++) {
348: String nsURI = reader.getNamespaceURI(i);
349: String nsPrefix = reader.getNamespacePrefix(i);
350: if (nsPrefix == null) {
351: nsPrefix = "";
352: }
353:
354: if (nsPrefix.length() == 0) {
355: writer.writeDefaultNamespace(nsURI);
356: } else {
357: writer.writeNamespace(nsPrefix, nsURI);
358: }
359:
360: if (nsURI.equals(uri) && nsPrefix.equals(prefix)) {
361: writeElementNS = false;
362: }
363: }
364:
365: // Check if the namespace still needs to be written.
366: // We need this check because namespace writing works
367: // different on Woodstox and the RI.
368: if (writeElementNS) {
369: if (prefix == null || prefix.length() == 0) {
370: writer.writeDefaultNamespace(uri);
371: } else {
372: writer.writeNamespace(prefix, uri);
373: }
374: }
375:
376: // Write out attributes
377: for (int i = 0; i < reader.getAttributeCount(); i++) {
378: String ns = reader.getAttributeNamespace(i);
379: String nsPrefix = reader.getAttributePrefix(i);
380: if (ns == null || ns.length() == 0) {
381: writer.writeAttribute(reader.getAttributeLocalName(i),
382: reader.getAttributeValue(i));
383: } else if (nsPrefix == null || nsPrefix.length() == 0) {
384: writer.writeAttribute(reader.getAttributeNamespace(i),
385: reader.getAttributeLocalName(i), reader
386: .getAttributeValue(i));
387: } else {
388: writer.writeAttribute(reader.getAttributePrefix(i),
389: reader.getAttributeNamespace(i), reader
390: .getAttributeLocalName(i), reader
391: .getAttributeValue(i));
392: }
393:
394: }
395: }
396:
397: public static void writeDocument(Document d,
398: XMLStreamWriter writer, boolean repairing)
399: throws XMLStreamException {
400: writeDocument(d, writer, true, repairing);
401: }
402:
403: public static void writeDocument(Document d,
404: XMLStreamWriter writer, boolean writeProlog,
405: boolean repairing) throws XMLStreamException {
406: if (writeProlog) {
407: writer.writeStartDocument();
408: }
409:
410: Element root = d.getDocumentElement();
411: writeElement(root, writer, repairing);
412:
413: if (writeProlog) {
414: writer.writeEndDocument();
415: }
416: }
417:
418: /**
419: * Writes an Element to an XMLStreamWriter. The writer must already have
420: * started the doucment (via writeStartDocument()). Also, this probably
421: * won't work with just a fragment of a document. The Element should be the
422: * root element of the document.
423: *
424: * @param e
425: * @param writer
426: * @throws XMLStreamException
427: */
428: public static void writeElement(Element e, XMLStreamWriter writer,
429: boolean repairing) throws XMLStreamException {
430: writeElement(e, writer, repairing, true);
431: }
432:
433: /**
434: * Writes an Element to an XMLStreamWriter. The writer must already have
435: * started the document (via writeStartDocument()). Also, this probably
436: * won't work with just a fragment of a document. The Element should be the
437: * root element of the document.
438: *
439: * @param e
440: * @param writer
441: * @param endElement true iff the element should be ended
442: * @throws XMLStreamException
443: */
444: public static void writeElement(Element e, XMLStreamWriter writer,
445: boolean repairing, boolean endElement)
446: throws XMLStreamException {
447: String prefix = e.getPrefix();
448: String ns = e.getNamespaceURI();
449: String localName = e.getLocalName();
450:
451: // System.out.println("local name : " + localName + " URI: " + ns + " Prefix :" + prefix);
452: if (prefix == null) {
453: prefix = "";
454: }
455: if (localName == null) {
456: localName = e.getNodeName();
457:
458: if (localName == null) {
459: throw new IllegalStateException(
460: "Element's local name cannot be null!");
461: }
462: }
463:
464: String decUri = writer.getNamespaceContext().getNamespaceURI(
465: prefix);
466: boolean declareNamespace = decUri == null || !decUri.equals(ns);
467:
468: if (ns == null || ns.length() == 0) {
469: writer.writeStartElement(localName);
470: } else {
471: // System.out.println("Calling writeStartElement for local name : "
472: // + localName + " URI: " + ns + " Prefix :" + prefix);
473: writer.writeStartElement(prefix, localName, ns);
474: }
475:
476: NamedNodeMap attrs = e.getAttributes();
477: for (int i = 0; i < attrs.getLength(); i++) {
478: Node attr = attrs.item(i);
479:
480: String name = attr.getNodeName();
481: String attrPrefix = "";
482: int prefixIndex = name.indexOf(':');
483: if (prefixIndex != -1) {
484: attrPrefix = name.substring(0, prefixIndex);
485: name = name.substring(prefixIndex + 1);
486: }
487:
488: if ("xmlns".equals(attrPrefix)) {
489: // System.out.println("WriteNamespace is called for prefix : "
490: // + name + " namespace :" + attr.getNodeValue());
491: writer.writeNamespace(name, attr.getNodeValue());
492: if (name.equals(prefix)
493: && attr.getNodeValue().equals(ns)) {
494: declareNamespace = false;
495: }
496: } else {
497: if ("xmlns".equals(name) && "".equals(attrPrefix)) {
498: writer.writeNamespace("", attr.getNodeValue());
499: if (attr.getNodeValue().equals(ns)) {
500: declareNamespace = false;
501: }
502: } else {
503: writer.writeAttribute(attrPrefix, attr
504: .getNamespaceURI(), name, attr
505: .getNodeValue());
506: }
507: }
508: }
509:
510: if (declareNamespace && repairing) {
511: if (ns == null) {
512: writer.writeNamespace(prefix, "");
513: } else {
514: writer.writeNamespace(prefix, ns);
515: }
516: }
517:
518: NodeList nodes = e.getChildNodes();
519: for (int i = 0; i < nodes.getLength(); i++) {
520: Node n = nodes.item(i);
521: writeNode(n, writer, repairing);
522: }
523:
524: if (endElement) {
525: writer.writeEndElement();
526: }
527: }
528:
529: public static void writeNode(Node n, XMLStreamWriter writer,
530: boolean repairing) throws XMLStreamException {
531: if (n instanceof Element) {
532: writeElement((Element) n, writer, repairing);
533: } else if (n instanceof Text) {
534: writer.writeCharacters(((Text) n).getNodeValue());
535: } else if (n instanceof CDATASection) {
536: writer.writeCData(((CDATASection) n).getData());
537: } else if (n instanceof Comment) {
538: writer.writeComment(((Comment) n).getData());
539: } else if (n instanceof EntityReference) {
540: writer.writeEntityRef(((EntityReference) n).getNodeValue());
541: } else if (n instanceof ProcessingInstruction) {
542: ProcessingInstruction pi = (ProcessingInstruction) n;
543: writer.writeProcessingInstruction(pi.getTarget(), pi
544: .getData());
545: } else if (n instanceof Document) {
546: writeDocument((Document) n, writer, repairing);
547: }
548: }
549:
550: public static Document read(XMLStreamReader reader)
551: throws XMLStreamException {
552: Document doc = DOMUtils.createDocument();
553: readDocElements(doc, reader, true);
554: return doc;
555: }
556:
557: public static Document read(DocumentBuilder builder,
558: XMLStreamReader reader, boolean repairing)
559: throws XMLStreamException {
560: Document doc = builder.newDocument();
561:
562: readDocElements(doc, reader, repairing);
563:
564: return doc;
565: }
566:
567: /**
568: * @param parent
569: * @return
570: */
571: private static Document getDocument(Node parent) {
572: return (parent instanceof Document) ? (Document) parent
573: : parent.getOwnerDocument();
574: }
575:
576: /**
577: * @param parent
578: * @param reader
579: * @return
580: * @throws XMLStreamException
581: */
582: private static Element startElement(Node parent,
583: XMLStreamReader reader, boolean repairing)
584: throws XMLStreamException {
585: Document doc = getDocument(parent);
586:
587: Element e = doc.createElementNS(reader.getNamespaceURI(),
588: reader.getLocalName());
589: if (reader.getPrefix() != null) {
590: e.setPrefix(reader.getPrefix());
591: }
592:
593: parent.appendChild(e);
594:
595: for (int ns = 0; ns < reader.getNamespaceCount(); ns++) {
596: String uri = reader.getNamespaceURI(ns);
597: String prefix = reader.getNamespacePrefix(ns);
598:
599: declare(e, uri, prefix);
600: }
601:
602: for (int att = 0; att < reader.getAttributeCount(); att++) {
603: String name = reader.getAttributeLocalName(att);
604: String prefix = reader.getAttributePrefix(att);
605: if (prefix != null && prefix.length() > 0) {
606: name = prefix + ":" + name;
607: }
608:
609: Attr attr = doc.createAttributeNS(reader
610: .getAttributeNamespace(att), name);
611: attr.setValue(reader.getAttributeValue(att));
612: e.setAttributeNode(attr);
613: }
614:
615: reader.next();
616:
617: readDocElements(e, reader, repairing);
618:
619: if (repairing
620: && !isDeclared(e, reader.getNamespaceURI(), reader
621: .getPrefix())) {
622: declare(e, reader.getNamespaceURI(), reader.getPrefix());
623: }
624:
625: return e;
626: }
627:
628: private static boolean isDeclared(Element e, String namespaceURI,
629: String prefix) {
630: Attr att;
631: if (prefix != null && prefix.length() > 0) {
632: att = e.getAttributeNodeNS(XML_NS, "xmlns:" + prefix);
633: } else {
634: att = e.getAttributeNode("xmlns");
635: }
636:
637: if (att != null && att.getNodeValue().equals(namespaceURI)) {
638: return true;
639: }
640:
641: if (e.getParentNode() instanceof Element) {
642: return isDeclared((Element) e.getParentNode(),
643: namespaceURI, prefix);
644: }
645:
646: return false;
647: }
648:
649: /**
650: * @param parent
651: * @param reader
652: * @throws XMLStreamException
653: */
654: public static void readDocElements(Node parent,
655: XMLStreamReader reader, boolean repairing)
656: throws XMLStreamException {
657: Document doc = getDocument(parent);
658:
659: int event = reader.getEventType();
660: while (reader.hasNext()) {
661: switch (event) {
662: case XMLStreamConstants.START_ELEMENT:
663: startElement(parent, reader, repairing);
664:
665: if (parent instanceof Document) {
666: if (reader.hasNext()) {
667: reader.next();
668: }
669:
670: return;
671: }
672: break;
673: case XMLStreamConstants.END_ELEMENT:
674: return;
675: case XMLStreamConstants.NAMESPACE:
676: break;
677: case XMLStreamConstants.ATTRIBUTE:
678: break;
679: case XMLStreamConstants.CHARACTERS:
680: if (parent != null) {
681: parent.appendChild(doc.createTextNode(reader
682: .getText()));
683: }
684:
685: break;
686: case XMLStreamConstants.COMMENT:
687: if (parent != null) {
688: parent.appendChild(doc.createComment(reader
689: .getText()));
690: }
691:
692: break;
693: case XMLStreamConstants.CDATA:
694: parent.appendChild(doc.createCDATASection(reader
695: .getText()));
696:
697: break;
698: case XMLStreamConstants.PROCESSING_INSTRUCTION:
699: parent.appendChild(doc.createProcessingInstruction(
700: reader.getPITarget(), reader.getPIData()));
701:
702: break;
703: case XMLStreamConstants.ENTITY_REFERENCE:
704: parent.appendChild(doc.createProcessingInstruction(
705: reader.getPITarget(), reader.getPIData()));
706:
707: break;
708: default:
709: break;
710: }
711:
712: if (reader.hasNext()) {
713: event = reader.next();
714: }
715: }
716: }
717:
718: private static void declare(Element node, String uri, String prefix) {
719: if (prefix != null && prefix.length() > 0) {
720: node.setAttributeNS(XML_NS, "xmlns:" + prefix, uri);
721: } else {
722: if (uri != null /* && uri.length() > 0 */) {
723: node.setAttributeNS(XML_NS, "xmlns", uri);
724: }
725: }
726: }
727:
728: /**
729: * @param in
730: * @param encoding
731: * @param ctx
732: * @return
733: */
734: public static XMLStreamReader createXMLStreamReader(InputStream in,
735: String encoding) {
736: if (encoding == null) {
737: encoding = "UTF-8";
738: }
739:
740: try {
741: return getXMLInputFactory().createXMLStreamReader(in,
742: encoding);
743: } catch (XMLStreamException e) {
744: throw new RuntimeException("Couldn't parse stream.", e);
745: }
746: }
747:
748: /**
749: * @param in
750: * @return
751: */
752: public static XMLStreamReader createXMLStreamReader(InputStream in) {
753: try {
754: return getXMLInputFactory().createXMLStreamReader(in);
755: } catch (XMLStreamException e) {
756: throw new RuntimeException("Couldn't parse stream.", e);
757: }
758: }
759:
760: public static XMLStreamReader createXMLStreamReader(Element el) {
761: return new W3CDOMStreamReader(el);
762: }
763:
764: public static XMLStreamReader createXMLStreamReader(Document doc) {
765: return new W3CDOMStreamReader(doc.getDocumentElement());
766: }
767:
768: public static XMLStreamReader createXMLStreamReader(Source source) {
769: try {
770: if (source instanceof DOMSource) {
771: DOMSource ds = (DOMSource) source;
772: Node nd = ds.getNode();
773: Element el = null;
774: if (nd instanceof Document) {
775: el = ((Document) nd).getDocumentElement();
776: } else if (nd instanceof Element) {
777: el = (Element) nd;
778: }
779:
780: if (null != el) {
781: return new W3CDOMStreamReader(el);
782: }
783: }
784:
785: return getXMLInputFactory().createXMLStreamReader(source);
786: } catch (XMLStreamException e) {
787: throw new RuntimeException("Couldn't parse stream.", e);
788: }
789: }
790:
791: /**
792: * @param reader
793: * @return
794: */
795: public static XMLStreamReader createXMLStreamReader(Reader reader) {
796:
797: try {
798: return getXMLInputFactory().createXMLStreamReader(reader);
799: } catch (XMLStreamException e) {
800: throw new RuntimeException("Couldn't parse stream.", e);
801: }
802: }
803:
804: /**
805: * Reads a QName from the element text. Reader must be positioned at the
806: * start tag.
807: */
808: public static QName readQName(XMLStreamReader reader)
809: throws XMLStreamException {
810: String value = reader.getElementText();
811: if (value == null) {
812: return null;
813: }
814:
815: int index = value.indexOf(":");
816:
817: if (index == -1) {
818: return new QName(value);
819: }
820:
821: String prefix = value.substring(0, index);
822: String localName = value.substring(index + 1);
823: String ns = reader.getNamespaceURI(prefix);
824:
825: if ((prefix != null && ns == null) || localName == null) {
826: throw new RuntimeException("Invalid QName in mapping: "
827: + value);
828: }
829:
830: if (ns == null) {
831: return new QName(localName);
832: }
833:
834: return new QName(ns, localName, prefix);
835: }
836:
837: /**
838: * Create a unique namespace uri/prefix combination.
839: *
840: * @param nsUri
841: * @return The namespace with the specified URI. If one doesn't exist, one
842: * is created.
843: * @throws XMLStreamException
844: */
845: public static String getUniquePrefix(XMLStreamWriter writer,
846: String namespaceURI, boolean declare)
847: throws XMLStreamException {
848: String prefix = writer.getPrefix(namespaceURI);
849: if (prefix == null) {
850: prefix = getUniquePrefix(writer);
851:
852: if (declare) {
853: writer.setPrefix(prefix, namespaceURI);
854: writer.writeNamespace(prefix, namespaceURI);
855: }
856: }
857: return prefix;
858: }
859:
860: public static String getUniquePrefix(XMLStreamWriter writer) {
861: int n = 1;
862:
863: NamespaceContext nc = writer.getNamespaceContext();
864: while (true) {
865: String nsPrefix = "ns" + n;
866:
867: if (nc == null || nc.getNamespaceURI(nsPrefix) == null) {
868: return nsPrefix;
869: }
870:
871: n++;
872: }
873: }
874:
875: public static void printXmlFragment(XMLStreamReader reader) {
876: XMLUtils.setIndention(4);
877: try {
878: LOG.info(XMLUtils.toString(StaxUtils.read(reader)));
879: } catch (XMLStreamException e) {
880: LOG.severe(e.getMessage());
881: }
882: }
883: }
|