0001: /*
0002: * $Id: XMLWriterUtils.java,v 1.6 2005/03/03 18:37:05 ryan_shoemaker Exp $
0003: *
0004: * Copyright (c) 2004, Christian Niles, unit12.net
0005: * All rights reserved.
0006: *
0007: * Redistribution and use in source and binary forms, with or without
0008: * modification, are permitted provided that the following conditions are met:
0009: *
0010: * * Redistributions of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * * Redistributions in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in the
0015: * documentation and/or other materials provided with the distribution.
0016: *
0017: * * Neither the name of Christian Niles, Unit12, nor the names of its
0018: * contributors may be used to endorse or promote products derived from
0019: * this software without specific prior written permission.
0020: *
0021: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031: * POSSIBILITY OF SUCH DAMAGE.
0032: *
0033: */
0034: package javanet.staxutils.io;
0035:
0036: import java.io.IOException;
0037: import java.io.Writer;
0038: import java.util.Iterator;
0039: import java.util.Map;
0040:
0041: import javanet.staxutils.XMLStreamUtils;
0042:
0043: import javax.xml.namespace.QName;
0044: import javax.xml.stream.XMLStreamException;
0045: import javax.xml.stream.XMLStreamWriter;
0046: import javax.xml.stream.events.Attribute;
0047: import javax.xml.stream.events.Characters;
0048: import javax.xml.stream.events.Comment;
0049: import javax.xml.stream.events.DTD;
0050: import javax.xml.stream.events.EndDocument;
0051: import javax.xml.stream.events.EndElement;
0052: import javax.xml.stream.events.EntityDeclaration;
0053: import javax.xml.stream.events.EntityReference;
0054: import javax.xml.stream.events.Namespace;
0055: import javax.xml.stream.events.NotationDeclaration;
0056: import javax.xml.stream.events.ProcessingInstruction;
0057: import javax.xml.stream.events.StartDocument;
0058: import javax.xml.stream.events.StartElement;
0059: import javax.xml.stream.events.XMLEvent;
0060:
0061: /**
0062: * Set of utility methods useful when writing XML.
0063: *
0064: * @author Christian Niles
0065: * @version $Revision: 1.6 $
0066: */
0067: public final class XMLWriterUtils {
0068:
0069: /**
0070: * Prevent instantiation.
0071: */
0072: private XMLWriterUtils() {
0073:
0074: }
0075:
0076: /**
0077: * Writes a quoted version of the given value, automatically determining the
0078: * appropriate quote character. The value will not be encoded before being
0079: * written. This method is useful when writing quoted DTD values, such as system
0080: * IDs.
0081: *
0082: * @param value The value to quote and output.
0083: * @param writer The destination stream.
0084: * @throws IOException If an error occurs writing to the stream.
0085: */
0086: public static final void writeQuotedValue(String value,
0087: Writer writer) throws IOException {
0088:
0089: char quoteChar = (value.indexOf('"') < 0 ? '"' : '\'');
0090: writer.write(quoteChar);
0091: writer.write(value);
0092: writer.write(quoteChar);
0093:
0094: }
0095:
0096: /**
0097: * Encodes the given value and writes it to the provided stream, wrapping it in
0098: * the appropriate quote character. This method is useful when writing attribute
0099: * values, and entity replacement text.
0100: *
0101: * @param value The value to encode, quote, and output.
0102: * @param writer The destination stream.
0103: * @throws IOException If an error occurs writing to the stream.
0104: */
0105: public static final void writeEncodedQuotedValue(String value,
0106: Writer writer) throws IOException {
0107:
0108: char quoteChar = (value.indexOf('"') < 0 ? '"' : '\'');
0109: writer.write(quoteChar);
0110: writeEncodedValue(value, quoteChar, writer);
0111: writer.write(quoteChar);
0112:
0113: }
0114:
0115: /**
0116: * Encodes the given value, and writes it to the stream, but does not actually
0117: * wrap the value in the quote character. The provided quote character is used to
0118: * determine whether a character must be encoded or not.
0119: *
0120: * @param value The value to encode and output.
0121: * @param quoteChar The quote character; used to determine which characters need
0122: * to be encoded.
0123: * @param writer The destination stream.
0124: * @throws IOException If an error occurs writing to the stream.
0125: */
0126: public static final void writeEncodedValue(String value,
0127: char quoteChar, Writer writer) throws IOException {
0128:
0129: // write value, encoding special characters along the way
0130: for (int i = 0, s = value.length(); i < s; i++) {
0131:
0132: char c = value.charAt(i);
0133: if (c == '\'') {
0134:
0135: writer.write(quoteChar == '\'' ? "'" : "'");
0136:
0137: } else if (c == '\"') {
0138:
0139: writer.write(quoteChar == '\"' ? """ : "\"");
0140:
0141: } else if (c == '\n') {
0142:
0143: writer.write("
");
0144:
0145: } else {
0146:
0147: writeEncodedCharacter(c, writer);
0148:
0149: }
0150:
0151: }
0152:
0153: }
0154:
0155: /**
0156: * Encodes the provided text and writes it to the provided stream. This method is
0157: * useful when writing character data, such as element text or CData sections,
0158: * and will not encode single or double quotes.
0159: *
0160: * @param text The text to write.
0161: * @param writer The destination stream.
0162: * @throws IOException If an error occurs writing to the stream.
0163: */
0164: public static final void writeEncodedText(CharSequence text,
0165: Writer writer) throws IOException {
0166:
0167: for (int i = 0, s = text.length(); i < s; i++) {
0168:
0169: writeEncodedCharacter(text.charAt(i), writer);
0170:
0171: }
0172:
0173: }
0174:
0175: public static final void writeEncodedText(char[] text, int start,
0176: int len, Writer writer) throws IOException {
0177:
0178: for (int i = start, s = start + len; i < s; i++) {
0179:
0180: writeEncodedCharacter(text[i], writer);
0181:
0182: }
0183:
0184: }
0185:
0186: /**
0187: * Encodes the provided character if needed, and writes it to an output stream.
0188: *
0189: * @param c The character to encode and output.
0190: * @param writer The destination stream.
0191: * @throws IOException If an error occurs writing to the stream.
0192: */
0193: public static final void writeEncodedCharacter(char c, Writer writer)
0194: throws IOException {
0195:
0196: if (c == '&') {
0197:
0198: writer.write("&");
0199:
0200: } else if (c == '<') {
0201:
0202: writer.write("<");
0203:
0204: } else if (c == '>') {
0205:
0206: writer.write(">");
0207:
0208: } else if (c == '\r') {
0209:
0210: writer.write("
");
0211:
0212: } else {
0213:
0214: writer.write(c);
0215:
0216: }
0217:
0218: }
0219:
0220: /**
0221: * Writes a qualified name to the provided stream.
0222: *
0223: * @param name The name to write.
0224: * @param writer The destination stream.
0225: * @throws IOException If an error occurs writing to the stream.
0226: */
0227: public static final void writeQName(QName name, Writer writer)
0228: throws IOException {
0229:
0230: String prefix = name.getPrefix();
0231: if (prefix != null && prefix.length() > 0) {
0232:
0233: writer.write(prefix);
0234: writer.write(':');
0235:
0236: }
0237:
0238: writer.write(name.getLocalPart());
0239:
0240: }
0241:
0242: /**
0243: * Writes a qualified name to the provided stream.
0244: *
0245: * @param prefix The prefix, or <code>null</code>
0246: * @param localPart The local part.
0247: * @param writer The destination stream.
0248: * @throws IOException If an error occurs writing to the stream.
0249: */
0250: public static final void writeQName(String prefix,
0251: String localPart, Writer writer) throws IOException {
0252:
0253: if (prefix != null && prefix.length() > 0) {
0254:
0255: writer.write(prefix);
0256: writer.write(':');
0257:
0258: }
0259:
0260: writer.write(localPart);
0261:
0262: }
0263:
0264: /**
0265: * Writes the given event to the provided {@link Writer}. This method
0266: * will delegate the actual task of writing to the stream to the appropriate
0267: * overloaded method.
0268: *
0269: * @param event The event to write.
0270: * @param writer The destination XML stream.
0271: * @throws IOException If an error occurs writing to the stream.
0272: * @throws XMLStreamException If the event is a StartElement and an error occurs
0273: * writing the Namespace or Attribute events.
0274: * @throws IllegalArgumentException If the event is an unknown type.
0275: */
0276: public static final void writeEvent(XMLEvent event, Writer writer)
0277: throws IOException, XMLStreamException {
0278:
0279: int eventType = event.getEventType();
0280: switch (eventType) {
0281:
0282: case XMLEvent.START_ELEMENT:
0283: writeStartElement(event.asStartElement(), false, writer);
0284: break;
0285:
0286: case XMLEvent.END_ELEMENT:
0287: writeEndElement(event.asEndElement(), writer);
0288: break;
0289:
0290: case XMLEvent.CHARACTERS:
0291: case XMLEvent.SPACE:
0292: case XMLEvent.CDATA:
0293: writeCharacters(event.asCharacters(), writer);
0294: break;
0295:
0296: case XMLEvent.COMMENT:
0297: writeComment((Comment) event, writer);
0298: break;
0299:
0300: case XMLEvent.ENTITY_REFERENCE:
0301: writeEntityReference((EntityReference) event, writer);
0302: break;
0303:
0304: case XMLEvent.PROCESSING_INSTRUCTION:
0305: writeProcessingInstruction((ProcessingInstruction) event,
0306: writer);
0307: break;
0308:
0309: case XMLEvent.DTD:
0310: writeDTD((DTD) event, writer);
0311: break;
0312:
0313: case XMLEvent.START_DOCUMENT:
0314: writeStartDocument((StartDocument) event, writer);
0315: break;
0316:
0317: case XMLEvent.END_DOCUMENT:
0318: writeEndDocument((EndDocument) event, writer);
0319: break;
0320:
0321: case XMLEvent.NAMESPACE:
0322: writeNamespace((Namespace) event, writer);
0323: break;
0324:
0325: case XMLEvent.ATTRIBUTE:
0326: writeAttribute((Attribute) event, writer);
0327: break;
0328:
0329: case XMLEvent.ENTITY_DECLARATION:
0330: writeEntityDeclaration((EntityDeclaration) event, writer);
0331: break;
0332:
0333: case XMLEvent.NOTATION_DECLARATION:
0334: writeNotationDeclaration((NotationDeclaration) event,
0335: writer);
0336: break;
0337:
0338: default:
0339: throw new IllegalArgumentException("Unrecognized event ("
0340: + XMLStreamUtils.getEventTypeName(eventType)
0341: + "): " + event);
0342:
0343: }
0344:
0345: }
0346:
0347: /**
0348: * Writes a {@link StartDocument} to the provided stream.
0349: *
0350: * @param start The {@link StartDocument} to write.
0351: * @param writer The destination stream.
0352: * @throws IOException If an error occurs writing to the stream.
0353: */
0354: public static final void writeStartDocument(StartDocument start,
0355: Writer writer) throws IOException {
0356:
0357: String version = start.getVersion();
0358: String encoding = start.getCharacterEncodingScheme();
0359:
0360: if (start.standaloneSet()) {
0361:
0362: writeStartDocument(version, encoding, start.isStandalone(),
0363: writer);
0364:
0365: } else {
0366:
0367: writeStartDocument(version, encoding, writer);
0368:
0369: }
0370:
0371: }
0372:
0373: /**
0374: * Writes a default XML declaration to the provided stream.
0375: *
0376: * @param writer The destination stream.
0377: * @throws IOException If an error occurs writing to the stream.
0378: */
0379: public static final void writeStartDocument(Writer writer)
0380: throws IOException {
0381:
0382: writeStartDocument("1.0", null, null, writer);
0383:
0384: }
0385:
0386: /**
0387: * Writes an XML declaration to the provided stream.
0388: *
0389: * @param version The xml version definition.
0390: * @param writer The destination stream.
0391: * @throws IOException If an error occurs writing to the stream.
0392: */
0393: public static final void writeStartDocument(String version,
0394: Writer writer) throws IOException {
0395:
0396: writeStartDocument(version, null, null, writer);
0397:
0398: }
0399:
0400: /**
0401: * Writes an XML declaration to the provided stream.
0402: *
0403: * @param version The xml version definition.
0404: * @param encoding The document encoding, or <code>null</code>
0405: * @param writer The destination stream.
0406: * @throws IOException If an error occurs writing to the stream.
0407: */
0408: public static final void writeStartDocument(String version,
0409: String encoding, Writer writer) throws IOException {
0410:
0411: writeStartDocument(version, encoding, null, writer);
0412:
0413: }
0414:
0415: /**
0416: * Writes an XML declaration to the provided stream.
0417: *
0418: * @param version The xml version definition.
0419: * @param encoding The document encoding, or <code>null</code>
0420: * @param standalone The standalone definition
0421: * @param writer The destination stream.
0422: * @throws IOException If an error occurs writing to the stream.
0423: */
0424: public static final void writeStartDocument(String version,
0425: String encoding, boolean standalone, Writer writer)
0426: throws IOException {
0427:
0428: writeStartDocument(version, encoding, (standalone ? "yes"
0429: : "no"), writer);
0430:
0431: }
0432:
0433: /**
0434: * Writes an XML declaration to the provided stream.
0435: *
0436: * @param version The xml version definition.
0437: * @param encoding The document encoding, or <code>null</code>
0438: * @param standalone The standalone definition, or <code>null</code>
0439: * @param writer The destination stream.
0440: * @throws IOException If an error occurs writing to the stream.
0441: */
0442: public static final void writeStartDocument(String version,
0443: String encoding, String standalone, Writer writer)
0444: throws IOException {
0445:
0446: writer.write("<?xml version=");
0447: XMLWriterUtils.writeQuotedValue(version, writer);
0448:
0449: if (encoding != null) {
0450:
0451: writer.write(" encoding=");
0452: XMLWriterUtils.writeQuotedValue(encoding, writer);
0453:
0454: }
0455:
0456: if (standalone != null) {
0457:
0458: writer.write(" standalone=");
0459: XMLWriterUtils.writeQuotedValue(standalone, writer);
0460:
0461: }
0462:
0463: writer.write("?>");
0464:
0465: }
0466:
0467: /**
0468: * Writes an {@link EndDocument} to the provided stream.
0469: *
0470: * @param end The {@link EndDocument} to write.
0471: * @param writer The destination stream.
0472: * @throws IOException If an error occurs writing to the stream.
0473: */
0474: public static final void writeEndDocument(EndDocument end,
0475: Writer writer) throws IOException {
0476:
0477: writeEndDocument(writer);
0478:
0479: }
0480:
0481: /**
0482: * Writes an document ending to the provided stream.
0483: *
0484: * @param writer The destination stream.
0485: * @throws IOException If an error occurs writing to the stream.
0486: */
0487: public static final void writeEndDocument(Writer writer)
0488: throws IOException {
0489:
0490: // nothing to write?
0491:
0492: }
0493:
0494: /**
0495: * Writes a {@link StartElement} event to the provided stream.
0496: *
0497: * @param start The {@link StartElement} event to write.
0498: * @param writer The destination stream.
0499: * @throws IOException If an error occurs writing to the stream.
0500: * @throws XMLStreamException If an error occurs writing any namespaces or
0501: * attribute events.
0502: */
0503: public static final void writeStartElement(StartElement start,
0504: Writer writer) throws IOException, XMLStreamException {
0505:
0506: writeStartElement(start.getName(), start.getAttributes(), start
0507: .getNamespaces(), false, writer);
0508:
0509: }
0510:
0511: /**
0512: * Writes a {@link StartElement} event to the provided stream.
0513: *
0514: * @param start The {@link StartElement} event to write.
0515: * @param empty Whether the element is empty.
0516: * @param writer The destination stream.
0517: * @throws IOException If an error occurs writing to the stream.
0518: * @throws XMLStreamException If an error occurs writing any namespaces or
0519: * attribute events.
0520: */
0521: public static final void writeStartElement(StartElement start,
0522: boolean empty, Writer writer) throws IOException,
0523: XMLStreamException {
0524:
0525: writeStartElement(start.getName(), start.getAttributes(), start
0526: .getNamespaces(), empty, writer);
0527:
0528: }
0529:
0530: /**
0531: * Writes a start tag and any associated namespaces and attributes to the
0532: * provided stream.
0533: *
0534: * @param name The tag name.
0535: * @param attributes An {@link Attribute} iterator, or <code>null</code>.
0536: * @param namespaces A {@link Namespace} iterator, or <code>null</code>.
0537: * @param writer The destination stream.
0538: * @throws IOException If an error occurs writing to the stream.
0539: * @throws XMLStreamException If an error occurs writing any namespaces or
0540: * attribute events.
0541: */
0542: public static final void writeStartElement(QName name,
0543: Iterator attributes, Iterator namespaces, Writer writer)
0544: throws IOException, XMLStreamException {
0545:
0546: writeStartElement(name, attributes, namespaces, false, writer);
0547:
0548: }
0549:
0550: /**
0551: * Writes a start tag and any associated namespaces and attributes to the
0552: * provided stream.
0553: *
0554: * @param name The tag name.
0555: * @param attributes An {@link Attribute} iterator, or <code>null</code>.
0556: * @param namespaces A {@link Namespace} iterator, or <code>null</code>.
0557: * @param empty Whether the element is empty.
0558: * @param writer The destination stream.
0559: * @throws IOException If an error occurs writing to the stream.
0560: * @throws XMLStreamException
0561: */
0562: public static final void writeStartElement(QName name,
0563: Iterator attributes, Iterator namespaces, boolean empty,
0564: Writer writer) throws IOException, XMLStreamException {
0565:
0566: writer.write('<');
0567: XMLWriterUtils.writeQName(name, writer);
0568:
0569: // send namespaces
0570: if (namespaces != null) {
0571:
0572: while (namespaces.hasNext()) {
0573:
0574: Namespace ns = (Namespace) namespaces.next();
0575: writer.write(' ');
0576: ns.writeAsEncodedUnicode(writer);
0577:
0578: }
0579:
0580: }
0581:
0582: // write attributes
0583: if (attributes != null) {
0584:
0585: while (attributes.hasNext()) {
0586:
0587: Attribute attr = (Attribute) attributes.next();
0588: writer.write(' ');
0589: attr.writeAsEncodedUnicode(writer);
0590:
0591: }
0592:
0593: }
0594:
0595: if (empty) {
0596:
0597: writer.write("/>");
0598:
0599: } else {
0600:
0601: writer.write('>');
0602:
0603: }
0604:
0605: }
0606:
0607: /**
0608: * Writes a start tag and any associated namespaces and attributes to the
0609: * provided stream.
0610: *
0611: * @param name The tag name.
0612: * @param attributes A {@link Map} of attribute values, keyed by their
0613: * {@link QName}s. If no attributes are present, this may be null.
0614: * @param namespaces A {@link Map} of namespace values, keyed by their
0615: * prefixes. If no namespaces are present, this may be null.
0616: * @param empty Whether the element is empty.
0617: * @param writer The destination stream.
0618: * @throws IOException If an error occurs writing to the stream.
0619: */
0620: public static final void writeStartElement(QName name,
0621: Map attributes, Map namespaces, boolean empty, Writer writer)
0622: throws IOException {
0623:
0624: writer.write('<');
0625: XMLWriterUtils.writeQName(name, writer);
0626:
0627: // send namespaces
0628: if (namespaces != null) {
0629:
0630: for (Iterator i = namespaces.entrySet().iterator(); i
0631: .hasNext();) {
0632:
0633: Map.Entry entry = (Map.Entry) i.next();
0634: writer.write(' ');
0635: writeNamespace((String) entry.getKey(), (String) entry
0636: .getValue(), writer);
0637:
0638: }
0639:
0640: }
0641:
0642: // write attributes
0643: if (attributes != null) {
0644:
0645: for (Iterator i = attributes.entrySet().iterator(); i
0646: .hasNext();) {
0647:
0648: Map.Entry entry = (Map.Entry) i.next();
0649: writer.write(' ');
0650: writeAttribute((QName) entry.getKey(), (String) entry
0651: .getValue(), writer);
0652:
0653: }
0654:
0655: }
0656:
0657: if (empty) {
0658:
0659: writer.write("/>");
0660:
0661: } else {
0662:
0663: writer.write('>');
0664:
0665: }
0666:
0667: }
0668:
0669: /**
0670: * Writes an {@link Attribute} to the provided stream.
0671: *
0672: * @param attr The {@link Attribute} to write.
0673: * @param writer The destination stream.
0674: * @throws IOException If an error occurs writing to the stream.
0675: */
0676: public static final void writeAttribute(Attribute attr,
0677: Writer writer) throws IOException {
0678:
0679: QName name = attr.getName();
0680: String value = attr.getValue();
0681: writeAttribute(name, value, writer);
0682:
0683: }
0684:
0685: /**
0686: * Writes an attribute to the provided stream.
0687: *
0688: * @param name The attribute name.
0689: * @param value The attribute value.
0690: * @param writer The destination stream.
0691: * @throws IOException If an error occurs writing to the stream.
0692: */
0693: public static final void writeAttribute(QName name, String value,
0694: Writer writer) throws IOException {
0695:
0696: XMLWriterUtils.writeQName(name, writer);
0697: writer.write('=');
0698: XMLWriterUtils.writeEncodedQuotedValue(value, writer);
0699:
0700: }
0701:
0702: /**
0703: * Writes a {@link Namespace} to the provided stream.
0704: *
0705: * @param ns The {@link Namespace} to write.
0706: * @param writer The destination stream.
0707: * @throws IOException If an error occurs writing to the stream.
0708: */
0709: public static final void writeNamespace(Namespace ns, Writer writer)
0710: throws IOException {
0711:
0712: String prefix = ns.getPrefix();
0713: String uri = ns.getNamespaceURI();
0714: writeNamespace(prefix, uri, writer);
0715:
0716: }
0717:
0718: /**
0719: * Writes a {@link Namespace} to the provided stream.
0720: *
0721: * @param prefix The namespace prefix, which may be <code>null</code>.
0722: * @param uri The namespace uri.
0723: * @param writer The destination stream.
0724: * @throws IOException If an error occurs writing to the stream.
0725: */
0726: public static final void writeNamespace(String prefix, String uri,
0727: Writer writer) throws IOException {
0728:
0729: writer.write("xmlns");
0730: if (prefix != null && prefix.length() > 0) {
0731:
0732: writer.write(':');
0733: writer.write(prefix);
0734:
0735: }
0736:
0737: writer.write('=');
0738: XMLWriterUtils.writeEncodedQuotedValue(uri, writer);
0739:
0740: }
0741:
0742: /**
0743: * Writes an {@link EndElement} to the provided stream.
0744: *
0745: * @param end The {@link EndElement} to write.
0746: * @param writer The destination stream.
0747: * @throws IOException If an error occurs writing to the stream.
0748: */
0749: public static final void writeEndElement(EndElement end,
0750: Writer writer) throws IOException {
0751:
0752: writeEndElement(end.getName(), writer);
0753:
0754: }
0755:
0756: /**
0757: * Writes an element end tag to the provided stream.
0758: *
0759: * @param name The element name.
0760: * @param writer The destination stream.
0761: * @throws IOException If an error occurs writing to the stream.
0762: */
0763: public static final void writeEndElement(QName name, Writer writer)
0764: throws IOException {
0765:
0766: writer.write("</");
0767: XMLWriterUtils.writeQName(name, writer);
0768: writer.write('>');
0769:
0770: }
0771:
0772: /**
0773: * Writes a {@link Characters} to the provided stream.
0774: *
0775: * @param chars The {@link Characters} to write.
0776: * @param writer The destination stream.
0777: * @throws IOException If an error occurs writing to the stream.
0778: */
0779: public static final void writeCharacters(Characters chars,
0780: Writer writer) throws IOException {
0781:
0782: if (chars.isCData()) {
0783:
0784: writeCData(chars.getData(), writer);
0785:
0786: } else {
0787:
0788: writeCharacters(chars.getData(), writer);
0789:
0790: }
0791:
0792: }
0793:
0794: /**
0795: * Writes a chunk of encoded text to the provided stream.
0796: *
0797: * @param text The text to write.
0798: * @param writer The destination stream.
0799: * @throws IOException If an error occurs writing to the stream.
0800: */
0801: public static final void writeCharacters(CharSequence text,
0802: Writer writer) throws IOException {
0803:
0804: XMLWriterUtils.writeEncodedText(text, writer);
0805:
0806: }
0807:
0808: /**
0809: * Writes a chunk of encoded text to the provided stream.
0810: *
0811: * @param data A character array containing the characters.
0812: * @param start The starting index into the array.
0813: * @param length The number of characters to write.
0814: * @param writer The destination stream.
0815: * @throws IOException If an error occurs writing to the stream.
0816: */
0817: public static final void writeCharacters(char[] data, int start,
0818: int length, Writer writer) throws IOException {
0819:
0820: XMLWriterUtils.writeEncodedText(data, start, length, writer);
0821:
0822: }
0823:
0824: /**
0825: * Writes a {@link Characters} to the provided stream.
0826: *
0827: * @param text The CData text to write.
0828: * @param writer The destination stream.
0829: * @throws IOException If an error occurs writing to the stream.
0830: */
0831: public static final void writeCData(String text, Writer writer)
0832: throws IOException {
0833:
0834: writer.write("<![CDATA[");
0835: writer.write(text);
0836: writer.write("]]>");
0837:
0838: }
0839:
0840: /**
0841: * Writes a {@link Characters} to the provided stream.
0842: *
0843: * @param data A character array containing the cdata text.
0844: * @param start The starting index into the array.
0845: * @param length The number of characters to write.
0846: * @param writer The destination stream.
0847: * @throws IOException If an error occurs writing to the stream.
0848: */
0849: public static final void writeCData(char[] data, int start,
0850: int length, Writer writer) throws IOException {
0851:
0852: writer.write("<![CDATA[");
0853: writer.write(data, start, length);
0854: writer.write("]]>");
0855:
0856: }
0857:
0858: /**
0859: * Writes a {@link Comment} to the provided stream.
0860: *
0861: * @param comment The {@link Comment} to write.
0862: * @param writer The destination stream.
0863: * @throws XMLStreamException If an error occurs writing to the stream.
0864: */
0865: public static final void writeComment(Comment comment, Writer writer)
0866: throws IOException {
0867:
0868: writeComment(comment.getText(), writer);
0869:
0870: }
0871:
0872: /**
0873: * Writes a comment to the provided stream.
0874: *
0875: * @param comment The comment text.
0876: * @param writer The destination stream.
0877: * @throws XMLStreamException If an error occurs writing to the stream.
0878: */
0879: public static final void writeComment(String comment, Writer writer)
0880: throws IOException {
0881:
0882: writer.write("<!--");
0883: writer.write(comment);
0884: writer.write("-->");
0885:
0886: }
0887:
0888: /**
0889: * Writes an {@link EntityReference} to the provided stream.
0890: *
0891: * @param entityRef The {@link EntityReference} to write.
0892: * @param writer The destination stream.
0893: * @throws XMLStreamException If an error occurs writing to the stream.
0894: */
0895: public static final void writeEntityReference(
0896: EntityReference entityRef, Writer writer)
0897: throws IOException {
0898:
0899: writeEntityReference(entityRef.getName(), writer);
0900:
0901: }
0902:
0903: /**
0904: * Writes an entity reference to the provided stream.
0905: *
0906: * @param entityRef The name of the entity reference.
0907: * @param writer The destination stream.
0908: * @throws XMLStreamException If an error occurs writing to the stream.
0909: */
0910: public static final void writeEntityReference(String entityRef,
0911: Writer writer) throws IOException {
0912:
0913: writer.write('&');
0914: writer.write(entityRef);
0915: writer.write(';');
0916:
0917: }
0918:
0919: /**
0920: * Writes an {@link EntityDeclaration} to the stream.
0921: *
0922: * @param declaration The {@link EntityDeclaration} to write.
0923: * @param writer The destination stream.
0924: * @throws IOException If an error occurs writing to the stream.
0925: */
0926: public static final void writeEntityDeclaration(
0927: EntityDeclaration declaration, Writer writer)
0928: throws IOException {
0929:
0930: String name = declaration.getName();
0931: String notation = declaration.getNotationName();
0932:
0933: String text = declaration.getReplacementText();
0934: if (text != null) {
0935:
0936: writeEntityDeclaration(name, text, notation, writer);
0937:
0938: } else {
0939:
0940: String publicId = declaration.getPublicId();
0941: String systemId = declaration.getSystemId();
0942:
0943: writeEntityDeclaration(name, publicId, systemId, notation,
0944: writer);
0945:
0946: }
0947:
0948: }
0949:
0950: /**
0951: * Writes an external entity declaration to the stream. Either or both of the
0952: * <code>publicId</code> and <code>systemId</code> parameters must be
0953: * non-<code>null</code>.
0954: *
0955: * @param name The entity name.
0956: * @param publicId The entity public ID, or <code>null</code>.
0957: * @param systemId The entity system ID, or <code>null</code>.
0958: * @param notation The notation name, or <code>null</code>.
0959: * @param writer The destination stream.
0960: * @throws IOException If an error occurs writing to the stream.
0961: */
0962: public static final void writeEntityDeclaration(String name,
0963: String publicId, String systemId, String notation,
0964: Writer writer) throws IOException {
0965:
0966: writer.write("<!ENTITY ");
0967: writer.write(name);
0968:
0969: if (publicId != null) {
0970:
0971: // write public/system ids
0972: writer.write("PUBLIC ");
0973: XMLWriterUtils.writeQuotedValue(publicId, writer);
0974: if (systemId != null) {
0975:
0976: writer.write(" ");
0977: XMLWriterUtils.writeQuotedValue(systemId, writer);
0978:
0979: }
0980:
0981: } else {
0982:
0983: // write system identifier
0984: writer.write("SYSTEM ");
0985: XMLWriterUtils.writeQuotedValue(systemId, writer);
0986:
0987: }
0988:
0989: // write optional notation
0990: if (notation != null) {
0991:
0992: writer.write(" NDATA");
0993: writer.write(notation);
0994:
0995: }
0996:
0997: writer.write(">");
0998:
0999: }
1000:
1001: /**
1002: * Writes an internal entity declaration to the stream.
1003: *
1004: * @param name The entity name.
1005: * @param text The entity replacement text.
1006: * @param notation The notation name, or <code>null</code>.
1007: * @param writer
1008: * @throws IOException
1009: */
1010: public static final void writeEntityDeclaration(String name,
1011: String text, String notation, Writer writer)
1012: throws IOException {
1013:
1014: writer.write("<!ENTITY ");
1015: writer.write(name);
1016:
1017: XMLWriterUtils.writeEncodedQuotedValue(text, writer);
1018:
1019: // write optional notation
1020: if (notation != null) {
1021:
1022: writer.write(" NDATA");
1023: writer.write(notation);
1024:
1025: }
1026:
1027: writer.write(">");
1028:
1029: }
1030:
1031: /**
1032: * Writes a {@link NotationDeclaration} to the stream.
1033: *
1034: * @param declaration The {@link NotationDeclaration} to write.
1035: * @param writer The destination stream.
1036: * @throws IOException If an error occurs writing to the stream.
1037: */
1038: public static final void writeNotationDeclaration(
1039: NotationDeclaration declaration, Writer writer)
1040: throws IOException {
1041:
1042: String name = declaration.getName();
1043: String publicId = declaration.getPublicId();
1044: String systemId = declaration.getSystemId();
1045:
1046: writeNotationDeclaration(name, publicId, systemId, writer);
1047:
1048: }
1049:
1050: /**
1051: * Writes a notation declaration to the stream. Either or both of the
1052: * <code>publicId</code> and <code>systemId</code> parameters must be
1053: * non-<code>null</code>.
1054: *
1055: * @param name The notation name.
1056: * @param publicId The entity public ID, or <code>null</code>.
1057: * @param systemId The entity system ID, or <code>null</code>.
1058: * @param writer The destination stream.
1059: * @throws IOException If an error occurs writing to the stream.
1060: */
1061: public static final void writeNotationDeclaration(String name,
1062: String publicId, String systemId, Writer writer)
1063: throws IOException {
1064:
1065: writer.write("<!NOTATION ");
1066: writer.write(name);
1067:
1068: if (publicId != null) {
1069:
1070: // write public/system ids
1071: writer.write("PUBLIC ");
1072: XMLWriterUtils.writeQuotedValue(publicId, writer);
1073: if (systemId != null) {
1074:
1075: writer.write(" ");
1076: XMLWriterUtils.writeQuotedValue(systemId, writer);
1077:
1078: }
1079:
1080: } else {
1081:
1082: // write system identifier
1083: writer.write("SYSTEM ");
1084: XMLWriterUtils.writeQuotedValue(systemId, writer);
1085:
1086: }
1087:
1088: writer.write(">");
1089:
1090: }
1091:
1092: /**
1093: * Writes a {@link ProcessingInstruction} to the provided stream.
1094: *
1095: * @param procInst The {@link ProcessingInstruction} to write.
1096: * @param writer The destination stream.
1097: * @throws XMLStreamException If an error occurs writing to the stream.
1098: */
1099: public static final void writeProcessingInstruction(
1100: ProcessingInstruction procInst, Writer writer)
1101: throws IOException {
1102:
1103: writeProcessingInstruction(procInst.getTarget(), procInst
1104: .getData(), writer);
1105:
1106: }
1107:
1108: /**
1109: * Writes a {@link ProcessingInstruction} to the provided stream.
1110: *
1111: * @param target The instruction target.
1112: * @param data The instruction data, or <code>null</code>.
1113: * @param writer The destination stream.
1114: * @throws XMLStreamException If an error occurs writing to the stream.
1115: */
1116: public static final void writeProcessingInstruction(String target,
1117: String data, Writer writer) throws IOException {
1118:
1119: writer.write("<?");
1120: writer.write(target);
1121:
1122: if (data != null) {
1123:
1124: writer.write(' ');
1125: writer.write(data);
1126:
1127: }
1128:
1129: writer.write("?>");
1130:
1131: }
1132:
1133: /**
1134: * Writes a {@link DTD} to the provided stream.
1135: *
1136: * @param dtd The {@link DTD} to write.
1137: * @param writer The destination stream.
1138: * @throws IOException If an error occurs writing to the stream.
1139: */
1140: public static final void writeDTD(DTD dtd, Writer writer)
1141: throws IOException {
1142:
1143: writeDTD(dtd, writer);
1144:
1145: }
1146:
1147: /**
1148: * Writes a dtd to the provided stream.
1149: *
1150: * @param dtd The dtd to write.
1151: * @param writer The destination stream.
1152: * @throws IOException If an error occurs writing to the stream.
1153: */
1154: public static final void writeDTD(String dtd, Writer writer)
1155: throws IOException {
1156:
1157: writer.write(dtd);
1158:
1159: }
1160:
1161: /**
1162: * Writes the given event to the provided {@link XMLStreamWriter}. This method
1163: * will delegate the actual task of writing to the stream to the appropriate
1164: * overloaded method.
1165: *
1166: * @param event The event to write.
1167: * @param writer The destination XML stream.
1168: * @throws XMLStreamException If an error occurs writing the event.
1169: */
1170: public static final void writeEvent(XMLEvent event,
1171: XMLStreamWriter writer) throws XMLStreamException {
1172:
1173: int eventType = event.getEventType();
1174: switch (eventType) {
1175:
1176: case XMLEvent.START_ELEMENT:
1177: writeStartElement(event.asStartElement(), false, writer);
1178: break;
1179:
1180: case XMLEvent.END_ELEMENT:
1181: writeEndElement(event.asEndElement(), writer);
1182: break;
1183:
1184: case XMLEvent.CHARACTERS:
1185: case XMLEvent.SPACE:
1186: case XMLEvent.CDATA:
1187: writeCharacters(event.asCharacters(), writer);
1188: break;
1189:
1190: case XMLEvent.COMMENT:
1191: writeComment((Comment) event, writer);
1192: break;
1193:
1194: case XMLEvent.ENTITY_REFERENCE:
1195: writeEntityReference((EntityReference) event, writer);
1196: break;
1197:
1198: case XMLEvent.PROCESSING_INSTRUCTION:
1199: writeProcessingInstruction((ProcessingInstruction) event,
1200: writer);
1201: break;
1202:
1203: case XMLEvent.DTD:
1204: writeDTD((DTD) event, writer);
1205: break;
1206:
1207: case XMLEvent.START_DOCUMENT:
1208: writeStartDocument((StartDocument) event, writer);
1209: break;
1210:
1211: case XMLEvent.END_DOCUMENT:
1212: writeEndDocument((EndDocument) event, writer);
1213: break;
1214:
1215: case XMLEvent.NAMESPACE:
1216: writeNamespace((Namespace) event, writer);
1217: break;
1218:
1219: case XMLEvent.ATTRIBUTE:
1220: writeAttribute((Attribute) event, writer);
1221: break;
1222:
1223: default:
1224: throw new XMLStreamException("Unrecognized event ("
1225: + XMLStreamUtils.getEventTypeName(eventType)
1226: + "): " + event);
1227:
1228: }
1229:
1230: }
1231:
1232: /**
1233: * Writes a {@link StartElement} event to the provided stream.
1234: *
1235: * @param start The {@link StartElement} event to write.
1236: * @param empty Whether the element is empty.
1237: * @param writer The destination stream.
1238: * @throws XMLStreamException If an error occurs writing to the stream.
1239: */
1240: public static final void writeStartElement(StartElement start,
1241: boolean empty, XMLStreamWriter writer)
1242: throws XMLStreamException {
1243:
1244: QName name = start.getName();
1245: String nsURI = name.getNamespaceURI();
1246: String localName = name.getLocalPart();
1247: String prefix = name.getPrefix();
1248:
1249: if (prefix != null && prefix.length() > 0) {
1250:
1251: if (empty) {
1252:
1253: writer.writeEmptyElement(prefix, localName, nsURI);
1254:
1255: } else {
1256:
1257: writer.writeStartElement(prefix, localName, nsURI);
1258:
1259: }
1260:
1261: } else if (nsURI != null && nsURI.length() > 0) {
1262:
1263: if (empty) {
1264:
1265: writer.writeEmptyElement(nsURI, localName);
1266:
1267: } else {
1268:
1269: writer.writeStartElement(nsURI, localName);
1270:
1271: }
1272:
1273: } else {
1274:
1275: if (empty) {
1276:
1277: writer.writeEmptyElement(localName);
1278:
1279: } else {
1280:
1281: writer.writeStartElement(localName);
1282:
1283: }
1284:
1285: }
1286:
1287: // send namespaces first
1288: Iterator nsIter = start.getNamespaces();
1289: while (nsIter.hasNext()) {
1290:
1291: Namespace ns = (Namespace) nsIter.next();
1292: writeNamespace(ns, writer);
1293:
1294: }
1295:
1296: // write attributes
1297: Iterator attrIter = start.getAttributes();
1298: while (attrIter.hasNext()) {
1299:
1300: Attribute attr = (Attribute) attrIter.next();
1301: writeAttribute(attr, writer);
1302:
1303: }
1304:
1305: }
1306:
1307: /**
1308: * Writes an {@link EndElement} to the provided stream.
1309: *
1310: * @param end The {@link EndElement} to write.
1311: * @param writer The destination stream.
1312: * @throws XMLStreamException If an error occurs writing to the stream.
1313: */
1314: public static final void writeEndElement(EndElement end,
1315: XMLStreamWriter writer) throws XMLStreamException {
1316:
1317: writer.writeEndElement();
1318:
1319: }
1320:
1321: /**
1322: * Writes an {@link Attribute} to the provided stream.
1323: *
1324: * @param attr The {@link Attribute} to write.
1325: * @param writer The destination stream.
1326: * @throws XMLStreamException If an error occurs writing to the stream.
1327: */
1328: public static final void writeAttribute(Attribute attr,
1329: XMLStreamWriter writer) throws XMLStreamException {
1330:
1331: QName name = attr.getName();
1332: String nsURI = name.getNamespaceURI();
1333: String localName = name.getLocalPart();
1334: String prefix = name.getPrefix();
1335: String value = attr.getValue();
1336:
1337: if (prefix != null) {
1338:
1339: writer.writeAttribute(prefix, nsURI, localName, value);
1340:
1341: } else if (nsURI != null) {
1342:
1343: writer.writeAttribute(nsURI, localName, value);
1344:
1345: } else {
1346:
1347: writer.writeAttribute(localName, value);
1348:
1349: }
1350:
1351: }
1352:
1353: /**
1354: * Writes a {@link Namespace} to the provided stream.
1355: *
1356: * @param ns The {@link Namespace} to write.
1357: * @param writer The destination stream.
1358: * @throws XMLStreamException If an error occurs writing to the stream.
1359: */
1360: public static final void writeNamespace(Namespace ns,
1361: XMLStreamWriter writer) throws XMLStreamException {
1362:
1363: if (ns.isDefaultNamespaceDeclaration()) {
1364:
1365: writer.writeDefaultNamespace(ns.getNamespaceURI());
1366:
1367: } else {
1368:
1369: writer.writeNamespace(ns.getPrefix(), ns.getNamespaceURI());
1370:
1371: }
1372:
1373: }
1374:
1375: /**
1376: * Writes a {@link StartDocument} to the provided stream.
1377: *
1378: * @param start The {@link StartDocument} to write.
1379: * @param writer The destination stream.
1380: * @throws XMLStreamException If an error occurs writing to the stream.
1381: */
1382: public static final void writeStartDocument(StartDocument start,
1383: XMLStreamWriter writer) throws XMLStreamException {
1384:
1385: String version = start.getVersion();
1386: if (start.encodingSet()) {
1387:
1388: String encoding = start.getCharacterEncodingScheme();
1389: writer.writeStartDocument(encoding, version);
1390:
1391: } else {
1392:
1393: writer.writeStartDocument(version);
1394:
1395: }
1396:
1397: }
1398:
1399: /**
1400: * Writes an {@link EndDocument} to the provided stream.
1401: *
1402: * @param end The {@link EndDocument} to write.
1403: * @param writer The destination stream.
1404: * @throws XMLStreamException If an error occurs writing to the stream.
1405: */
1406: public static final void writeEndDocument(EndDocument end,
1407: XMLStreamWriter writer) throws XMLStreamException {
1408:
1409: writer.writeEndDocument();
1410:
1411: }
1412:
1413: /**
1414: * Writes a {@link Characters} to the provided stream.
1415: *
1416: * @param chars The {@link Characters} to write.
1417: * @param writer The destination stream.
1418: * @throws XMLStreamException If an error occurs writing to the stream.
1419: */
1420: public static final void writeCharacters(Characters chars,
1421: XMLStreamWriter writer) throws XMLStreamException {
1422:
1423: if (chars.isCData()) {
1424:
1425: writer.writeCData(chars.getData());
1426:
1427: } else {
1428:
1429: writer.writeCharacters(chars.getData());
1430:
1431: }
1432:
1433: }
1434:
1435: /**
1436: * Writes a {@link Comment} to the provided stream.
1437: *
1438: * @param comment The {@link Comment} to write.
1439: * @param writer The destination stream.
1440: * @throws XMLStreamException If an error occurs writing to the stream.
1441: */
1442: public static final void writeComment(Comment comment,
1443: XMLStreamWriter writer) throws XMLStreamException {
1444:
1445: writer.writeComment(comment.getText());
1446:
1447: }
1448:
1449: /**
1450: * Writes an {@link EntityReference} to the provided stream.
1451: *
1452: * @param entityRef The {@link EntityReference} to write.
1453: * @param writer The destination stream.
1454: * @throws XMLStreamException If an error occurs writing to the stream.
1455: */
1456: public static final void writeEntityReference(
1457: EntityReference entityRef, XMLStreamWriter writer)
1458: throws XMLStreamException {
1459:
1460: writer.writeEntityRef(entityRef.getName());
1461:
1462: }
1463:
1464: /**
1465: * Writes a {@link ProcessingInstruction} to the provided stream.
1466: *
1467: * @param procInst The {@link ProcessingInstruction} to write.
1468: * @param writer The destination stream.
1469: * @throws XMLStreamException If an error occurs writing to the stream.
1470: */
1471: public static final void writeProcessingInstruction(
1472: ProcessingInstruction procInst, XMLStreamWriter writer)
1473: throws XMLStreamException {
1474:
1475: String data = procInst.getData();
1476: if (data != null) {
1477:
1478: writer.writeProcessingInstruction(procInst.getTarget(),
1479: data);
1480:
1481: } else {
1482:
1483: writer.writeProcessingInstruction(procInst.getTarget());
1484:
1485: }
1486:
1487: }
1488:
1489: /**
1490: * Writes a {@link DTD} to the provided stream.
1491: *
1492: * @param dtd The {@link DTD} to write.
1493: * @param writer The destination stream.
1494: * @throws XMLStreamException If an error occurs writing to the stream.
1495: */
1496: public static final void writeDTD(DTD dtd, XMLStreamWriter writer)
1497: throws XMLStreamException {
1498:
1499: writer.writeDTD(dtd.getDocumentTypeDeclaration());
1500:
1501: }
1502:
1503: }
|