123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599 |
- /*--
-
- $Id: XMLOutputter.java,v 1.116 2007/11/10 05:29:01 jhunter Exp $
-
- Copyright (C) 2000-2007 Jason Hunter & Brett McLaughlin.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions, and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions, and the disclaimer that follows
- these conditions in the documentation and/or other materials
- provided with the distribution.
-
- 3. The name "JDOM" must not be used to endorse or promote products
- derived from this software without prior written permission. For
- written permission, please contact <request_AT_jdom_DOT_org>.
-
- 4. Products derived from this software may not be called "JDOM", nor
- may "JDOM" appear in their name, without prior written permission
- from the JDOM Project Management <request_AT_jdom_DOT_org>.
-
- In addition, we request (but do not require) that you include in the
- end-user documentation provided with the redistribution and/or in the
- software itself an acknowledgement equivalent to the following:
- "This product includes software developed by the
- JDOM Project (http://www.jdom.org/)."
- Alternatively, the acknowledgment may be graphical using the logos
- available at http://www.jdom.org/images/logos.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-
- This software consists of voluntary contributions made by many
- individuals on behalf of the JDOM Project and was originally
- created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
- Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
- on the JDOM Project, please see <http://www.jdom.org/>.
-
- */
-
- package org.jdom.output;
-
- import java.io.*;
- import java.util.*;
-
- import javax.xml.transform.Result;
-
- import org.jdom.*;
-
- /**
- * Outputs a JDOM document as a stream of bytes. The outputter can manage many
- * styles of document formatting, from untouched to pretty printed. The default
- * is to output the document content exactly as created, but this can be changed
- * by setting a new Format object. For pretty-print output, use
- * <code>{@link Format#getPrettyFormat()}</code>. For whitespace-normalized
- * output, use <code>{@link Format#getCompactFormat()}</code>.
- * <p>
- * There are <code>{@link #output output(...)}</code> methods to print any of
- * the standard JDOM classes, including Document and Element, to either a Writer
- * or an OutputStream. <b>Warning</b>: When outputting to a Writer, make sure
- * the writer's encoding matches the encoding setting in the Format object. This
- * ensures the encoding in which the content is written (controlled by the
- * Writer configuration) matches the encoding placed in the document's XML
- * declaration (controlled by the XMLOutputter). Because a Writer cannot be
- * queried for its encoding, the information must be passed to the Format
- * manually in its constructor or via the
- * <code>{@link Format#setEncoding}</code> method. The default encoding is
- * UTF-8.
- * <p>
- * The methods <code>{@link #outputString outputString(...)}</code> are for
- * convenience only; for top performance you should call one of the <code>{@link
- * #output output(...)}</code> methods and pass in your own Writer or
- * OutputStream if possible.
- * <p>
- * XML declarations are always printed on their own line followed by a line
- * seperator (this doesn't change the semantics of the document). To omit
- * printing of the declaration use
- * <code>{@link Format#setOmitDeclaration}</code>. To omit printing of the
- * encoding in the declaration use <code>{@link Format#setOmitEncoding}</code>.
- * Unfortunatly there is currently no way to know the original encoding of the
- * document.
- * <p>
- * Empty elements are by default printed as <empty/>, but this can be
- * configured with <code>{@link Format#setExpandEmptyElements}</code> to cause
- * them to be expanded to <empty></empty>.
- *
- * @version $Revision: 1.116 $, $Date: 2007/11/10 05:29:01 $
- * @author Brett McLaughlin
- * @author Jason Hunter
- * @author Jason Reid
- * @author Wolfgang Werner
- * @author Elliotte Rusty Harold
- * @author David & Will (from Post Tool Design)
- * @author Dan Schaffer
- * @author Alex Chaffee
- * @author Bradley S. Huffman
- */
-
- public class XMLOutputter implements Cloneable {
-
- private static final String CVS_ID =
- "@(#) $RCSfile: XMLOutputter.java,v $ $Revision: 1.116 $ $Date: 2007/11/10 05:29:01 $ $Name: jdom_1_1 $";
-
- // For normal output
- private Format userFormat = Format.getRawFormat();
-
- // For xml:space="preserve"
- protected static final Format preserveFormat = Format.getRawFormat();
-
- // What's currently in use
- protected Format currentFormat = userFormat;
-
- /** Whether output escaping is enabled for the being processed
- * Element - default is <code>true</code> */
- private boolean escapeOutput = true;
-
- // * * * * * * * * * * Constructors * * * * * * * * * *
- // * * * * * * * * * * Constructors * * * * * * * * * *
-
- /**
- * This will create an <code>XMLOutputter</code> with the default
- * {@link Format} matching {@link Format#getRawFormat}.
- */
- public XMLOutputter() {
- }
-
- /**
- * This will create an <code>XMLOutputter</code> with the specified
- * format characteristics. Note the format object is cloned internally
- * before use.
- */
- public XMLOutputter(Format format) {
- userFormat = (Format) format.clone();
- currentFormat = userFormat;
- }
-
- /**
- * This will create an <code>XMLOutputter</code> with all the
- * options as set in the given <code>XMLOutputter</code>. Note
- * that <code>XMLOutputter two = (XMLOutputter)one.clone();</code>
- * would work equally well.
- *
- * @param that the XMLOutputter to clone
- */
- public XMLOutputter(XMLOutputter that) {
- this.userFormat = (Format) that.userFormat.clone();
- currentFormat = userFormat;
- }
-
- // * * * * * * * * * * Set parameters methods * * * * * * * * * *
- // * * * * * * * * * * Set parameters methods * * * * * * * * * *
-
- /**
- * Sets the new format logic for the outputter. Note the Format
- * object is cloned internally before use.
- *
- * @param newFormat the format to use for output
- */
- public void setFormat(Format newFormat) {
- this.userFormat = (Format) newFormat.clone();
- this.currentFormat = userFormat;
- }
-
- /**
- * Returns the current format in use by the outputter. Note the
- * Format object returned is a clone of the one used internally.
- */
- public Format getFormat() {
- return (Format) userFormat.clone();
- }
-
- // * * * * * * * * * * Output to a OutputStream * * * * * * * * * *
- // * * * * * * * * * * Output to a OutputStream * * * * * * * * * *
-
- /**
- * This will print the <code>Document</code> to the given output stream.
- * The characters are printed using the encoding specified in the
- * constructor, or a default of UTF-8.
- *
- * @param doc <code>Document</code> to format.
- * @param out <code>OutputStream</code> to use.
- * @throws IOException - if there's any problem writing.
- */
- public void output(Document doc, OutputStream out)
- throws IOException {
- Writer writer = makeWriter(out);
- output(doc, writer); // output() flushes
- }
-
- /**
- * Print out the <code>{@link DocType}</code>.
- *
- * @param doctype <code>DocType</code> to output.
- * @param out <code>OutputStream</code> to use.
- */
- public void output(DocType doctype, OutputStream out) throws IOException {
- Writer writer = makeWriter(out);
- output(doctype, writer); // output() flushes
- }
-
- /**
- * Print out an <code>{@link Element}</code>, including
- * its <code>{@link Attribute}</code>s, and all
- * contained (child) elements, etc.
- *
- * @param element <code>Element</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void output(Element element, OutputStream out) throws IOException {
- Writer writer = makeWriter(out);
- output(element, writer); // output() flushes
- }
-
- /**
- * This will handle printing out an <code>{@link
- * Element}</code>'s content only, not including its tag, and
- * attributes. This can be useful for printing the content of an
- * element that contains HTML, like "<description>JDOM is
- * <b>fun>!</description>".
- *
- * @param element <code>Element</code> to output.
- * @param out <code>OutputStream</code> to use.
- */
- public void outputElementContent(Element element, OutputStream out)
- throws IOException {
- Writer writer = makeWriter(out);
- outputElementContent(element, writer); // output() flushes
- }
-
- /**
- * This will handle printing out a list of nodes.
- * This can be useful for printing the content of an element that
- * contains HTML, like "<description>JDOM is
- * <b>fun>!</description>".
- *
- * @param list <code>List</code> of nodes.
- * @param out <code>OutputStream</code> to use.
- */
- public void output(List list, OutputStream out)
- throws IOException {
- Writer writer = makeWriter(out);
- output(list, writer); // output() flushes
- }
-
- /**
- * Print out a <code>{@link CDATA}</code> node.
- *
- * @param cdata <code>CDATA</code> to output.
- * @param out <code>OutputStream</code> to use.
- */
- public void output(CDATA cdata, OutputStream out) throws IOException {
- Writer writer = makeWriter(out);
- output(cdata, writer); // output() flushes
- }
-
- /**
- * Print out a <code>{@link Text}</code> node. Perfoms
- * the necessary entity escaping and whitespace stripping.
- *
- * @param text <code>Text</code> to output.
- * @param out <code>OutputStream</code> to use.
- */
- public void output(Text text, OutputStream out) throws IOException {
- Writer writer = makeWriter(out);
- output(text, writer); // output() flushes
- }
-
- /**
- * Print out a <code>{@link Comment}</code>.
- *
- * @param comment <code>Comment</code> to output.
- * @param out <code>OutputStream</code> to use.
- */
- public void output(Comment comment, OutputStream out) throws IOException {
- Writer writer = makeWriter(out);
- output(comment, writer); // output() flushes
- }
-
- /**
- * Print out a <code>{@link ProcessingInstruction}</code>.
- *
- * @param pi <code>ProcessingInstruction</code> to output.
- * @param out <code>OutputStream</code> to use.
- */
- public void output(ProcessingInstruction pi, OutputStream out)
- throws IOException {
- Writer writer = makeWriter(out);
- output(pi, writer); // output() flushes
- }
-
- /**
- * Print out a <code>{@link EntityRef}</code>.
- *
- * @param entity <code>EntityRef</code> to output.
- * @param out <code>OutputStream</code> to use.
- */
- public void output(EntityRef entity, OutputStream out) throws IOException {
- Writer writer = makeWriter(out);
- output(entity, writer); // output() flushes
- }
-
- /**
- * Get an OutputStreamWriter, using prefered encoding
- * (see {@link Format#setEncoding}).
- */
- private Writer makeWriter(OutputStream out)
- throws java.io.UnsupportedEncodingException {
- return makeWriter(out, userFormat.encoding);
- }
-
- /**
- * Get an OutputStreamWriter, use specified encoding.
- */
- private static Writer makeWriter(OutputStream out, String enc)
- throws java.io.UnsupportedEncodingException {
- // "UTF-8" is not recognized before JDK 1.1.6, so we'll translate
- // into "UTF8" which works with all JDKs.
- if ("UTF-8".equals(enc)) {
- enc = "UTF8";
- }
-
- Writer writer = new BufferedWriter(
- (new OutputStreamWriter(
- new BufferedOutputStream(out), enc)
- ));
- return writer;
- }
-
- // * * * * * * * * * * Output to a Writer * * * * * * * * * *
- // * * * * * * * * * * Output to a Writer * * * * * * * * * *
-
- /**
- * This will print the <code>Document</code> to the given Writer.
- *
- * <p>
- * Warning: using your own Writer may cause the outputter's
- * preferred character encoding to be ignored. If you use
- * encodings other than UTF-8, we recommend using the method that
- * takes an OutputStream instead.
- * </p>
- *
- * @param doc <code>Document</code> to format.
- * @param out <code>Writer</code> to use.
- * @throws IOException - if there's any problem writing.
- */
- public void output(Document doc, Writer out) throws IOException {
-
- printDeclaration(out, doc, userFormat.encoding);
-
- // Print out root element, as well as any root level
- // comments and processing instructions,
- // starting with no indentation
- List content = doc.getContent();
- int size = content.size();
- for (int i = 0; i < size; i++) {
- Object obj = content.get(i);
-
- if (obj instanceof Element) {
- printElement(out, doc.getRootElement(), 0,
- createNamespaceStack());
- }
- else if (obj instanceof Comment) {
- printComment(out, (Comment) obj);
- }
- else if (obj instanceof ProcessingInstruction) {
- printProcessingInstruction(out, (ProcessingInstruction) obj);
- }
- else if (obj instanceof DocType) {
- printDocType(out, doc.getDocType());
- // Always print line separator after declaration, helps the
- // output look better and is semantically inconsequential
- out.write(currentFormat.lineSeparator);
- }
- else {
- // XXX if we get here then we have a illegal content, for
- // now we'll just ignore it
- }
-
- newline(out);
- indent(out, 0);
- }
-
- // Output final line separator
- // We output this no matter what the newline flags say
- out.write(currentFormat.lineSeparator);
-
- out.flush();
- }
-
- /**
- * Print out the <code>{@link DocType}</code>.
- *
- * @param doctype <code>DocType</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void output(DocType doctype, Writer out) throws IOException {
- printDocType(out, doctype);
- out.flush();
- }
-
- /**
- * Print out an <code>{@link Element}</code>, including
- * its <code>{@link Attribute}</code>s, and all
- * contained (child) elements, etc.
- *
- * @param element <code>Element</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void output(Element element, Writer out) throws IOException {
- // If this is the root element we could pre-initialize the
- // namespace stack with the namespaces
- printElement(out, element, 0, createNamespaceStack());
- out.flush();
- }
-
- /**
- * This will handle printing out an <code>{@link
- * Element}</code>'s content only, not including its tag, and
- * attributes. This can be useful for printing the content of an
- * element that contains HTML, like "<description>JDOM is
- * <b>fun>!</description>".
- *
- * @param element <code>Element</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void outputElementContent(Element element, Writer out)
- throws IOException {
- List content = element.getContent();
- printContentRange(out, content, 0, content.size(),
- 0, createNamespaceStack());
- out.flush();
- }
-
- /**
- * This will handle printing out a list of nodes.
- * This can be useful for printing the content of an element that
- * contains HTML, like "<description>JDOM is
- * <b>fun>!</description>".
- *
- * @param list <code>List</code> of nodes.
- * @param out <code>Writer</code> to use.
- */
- public void output(List list, Writer out)
- throws IOException {
- printContentRange(out, list, 0, list.size(),
- 0, createNamespaceStack());
- out.flush();
- }
-
- /**
- * Print out a <code>{@link CDATA}</code> node.
- *
- * @param cdata <code>CDATA</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void output(CDATA cdata, Writer out) throws IOException {
- printCDATA(out, cdata);
- out.flush();
- }
-
- /**
- * Print out a <code>{@link Text}</code> node. Perfoms
- * the necessary entity escaping and whitespace stripping.
- *
- * @param text <code>Text</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void output(Text text, Writer out) throws IOException {
- printText(out, text);
- out.flush();
- }
-
- /**
- * Print out a <code>{@link Comment}</code>.
- *
- * @param comment <code>Comment</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void output(Comment comment, Writer out) throws IOException {
- printComment(out, comment);
- out.flush();
- }
-
- /**
- * Print out a <code>{@link ProcessingInstruction}</code>.
- *
- * @param pi <code>ProcessingInstruction</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void output(ProcessingInstruction pi, Writer out)
- throws IOException {
- boolean currentEscapingPolicy = currentFormat.ignoreTrAXEscapingPIs;
-
- // Output PI verbatim, disregarding TrAX escaping PIs.
- currentFormat.setIgnoreTrAXEscapingPIs(true);
- printProcessingInstruction(out, pi);
- currentFormat.setIgnoreTrAXEscapingPIs(currentEscapingPolicy);
-
- out.flush();
- }
-
- /**
- * Print out a <code>{@link EntityRef}</code>.
- *
- * @param entity <code>EntityRef</code> to output.
- * @param out <code>Writer</code> to use.
- */
- public void output(EntityRef entity, Writer out) throws IOException {
- printEntityRef(out, entity);
- out.flush();
- }
-
- // * * * * * * * * * * Output to a String * * * * * * * * * *
- // * * * * * * * * * * Output to a String * * * * * * * * * *
-
- /**
- * Return a string representing a document. Uses an internal
- * StringWriter. Warning: a String is Unicode, which may not match
- * the outputter's specified encoding.
- *
- * @param doc <code>Document</code> to format.
- */
- public String outputString(Document doc) {
- StringWriter out = new StringWriter();
- try {
- output(doc, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
- /**
- * Return a string representing a DocType. Warning: a String is
- * Unicode, which may not match the outputter's specified
- * encoding.
- *
- * @param doctype <code>DocType</code> to format.
- */
- public String outputString(DocType doctype) {
- StringWriter out = new StringWriter();
- try {
- output(doctype, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
- /**
- * Return a string representing an element. Warning: a String is
- * Unicode, which may not match the outputter's specified
- * encoding.
- *
- * @param element <code>Element</code> to format.
- */
- public String outputString(Element element) {
- StringWriter out = new StringWriter();
- try {
- output(element, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
- /**
- * Return a string representing a list of nodes. The list is
- * assumed to contain legal JDOM nodes.
- *
- * @param list <code>List</code> to format.
- */
- public String outputString(List list) {
- StringWriter out = new StringWriter();
- try {
- output(list, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
- /**
- * Return a string representing a CDATA node. Warning: a String is
- * Unicode, which may not match the outputter's specified
- * encoding.
- *
- * @param cdata <code>CDATA</code> to format.
- */
- public String outputString(CDATA cdata) {
- StringWriter out = new StringWriter();
- try {
- output(cdata, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
- /**
- * Return a string representing a Text node. Warning: a String is
- * Unicode, which may not match the outputter's specified
- * encoding.
- *
- * @param text <code>Text</code> to format.
- */
- public String outputString(Text text) {
- StringWriter out = new StringWriter();
- try {
- output(text, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
-
- /**
- * Return a string representing a comment. Warning: a String is
- * Unicode, which may not match the outputter's specified
- * encoding.
- *
- * @param comment <code>Comment</code> to format.
- */
- public String outputString(Comment comment) {
- StringWriter out = new StringWriter();
- try {
- output(comment, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
- /**
- * Return a string representing a PI. Warning: a String is
- * Unicode, which may not match the outputter's specified
- * encoding.
- *
- * @param pi <code>ProcessingInstruction</code> to format.
- */
- public String outputString(ProcessingInstruction pi) {
- StringWriter out = new StringWriter();
- try {
- output(pi, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
- /**
- * Return a string representing an entity. Warning: a String is
- * Unicode, which may not match the outputter's specified
- * encoding.
- *
- * @param entity <code>EntityRef</code> to format.
- */
- public String outputString(EntityRef entity) {
- StringWriter out = new StringWriter();
- try {
- output(entity, out); // output() flushes
- } catch (IOException e) { }
- return out.toString();
- }
-
- // * * * * * * * * * * Internal printing methods * * * * * * * * * *
- // * * * * * * * * * * Internal printing methods * * * * * * * * * *
-
- /**
- * This will handle printing of the declaration.
- * Assumes XML version 1.0 since we don't directly know.
- *
- * @param doc <code>Document</code> whose declaration to write.
- * @param out <code>Writer</code> to use.
- * @param encoding The encoding to add to the declaration
- */
- protected void printDeclaration(Writer out, Document doc,
- String encoding) throws IOException {
-
- // Only print the declaration if it's not being omitted
- if (!userFormat.omitDeclaration) {
- // Assume 1.0 version
- out.write("<?xml version=\"1.0\"");
- if (!userFormat.omitEncoding) {
- out.write(" encoding=\"" + encoding + "\"");
- }
- out.write("?>");
-
- // Print new line after decl always, even if no other new lines
- // Helps the output look better and is semantically
- // inconsequential
- out.write(currentFormat.lineSeparator);
- }
- }
-
- /**
- * This handle printing the DOCTYPE declaration if one exists.
- *
- * @param docType <code>Document</code> whose declaration to write.
- * @param out <code>Writer</code> to use.
- */
- protected void printDocType(Writer out, DocType docType)
- throws IOException {
-
- String publicID = docType.getPublicID();
- String systemID = docType.getSystemID();
- String internalSubset = docType.getInternalSubset();
- boolean hasPublic = false;
-
- out.write("<!DOCTYPE ");
- out.write(docType.getElementName());
- if (publicID != null) {
- out.write(" PUBLIC \"");
- out.write(publicID);
- out.write("\"");
- hasPublic = true;
- }
- if (systemID != null) {
- if (!hasPublic) {
- out.write(" SYSTEM");
- }
- out.write(" \"");
- out.write(systemID);
- out.write("\"");
- }
- if ((internalSubset != null) && (!internalSubset.equals(""))) {
- out.write(" [");
- out.write(currentFormat.lineSeparator);
- out.write(docType.getInternalSubset());
- out.write("]");
- }
- out.write(">");
- }
-
- /**
- * This will handle printing of comments.
- *
- * @param comment <code>Comment</code> to write.
- * @param out <code>Writer</code> to use.
- */
- protected void printComment(Writer out, Comment comment)
- throws IOException {
- out.write("<!--");
- out.write(comment.getText());
- out.write("-->");
- }
-
- /**
- * This will handle printing of processing instructions.
- *
- * @param pi <code>ProcessingInstruction</code> to write.
- * @param out <code>Writer</code> to use.
- */
- protected void printProcessingInstruction(Writer out, ProcessingInstruction pi
- ) throws IOException {
- String target = pi.getTarget();
- boolean piProcessed = false;
-
- if (currentFormat.ignoreTrAXEscapingPIs == false) {
- if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING)) {
- escapeOutput = false;
- piProcessed = true;
- }
- else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING)) {
- escapeOutput = true;
- piProcessed = true;
- }
- }
- if (piProcessed == false) {
- String rawData = pi.getData();
-
- // Write <?target data?> or if no data then just <?target?>
- if (!"".equals(rawData)) {
- out.write("<?");
- out.write(target);
- out.write(" ");
- out.write(rawData);
- out.write("?>");
- }
- else {
- out.write("<?");
- out.write(target);
- out.write("?>");
- }
- }
- }
-
- /**
- * This will handle printing a <code>{@link EntityRef}</code>.
- * Only the entity reference such as <code>&entity;</code>
- * will be printed. However, subclasses are free to override
- * this method to print the contents of the entity instead.
- *
- * @param entity <code>EntityRef</code> to output.
- * @param out <code>Writer</code> to use. */
- protected void printEntityRef(Writer out, EntityRef entity)
- throws IOException {
- out.write("&");
- out.write(entity.getName());
- out.write(";");
- }
-
- /**
- * This will handle printing of <code>{@link CDATA}</code> text.
- *
- * @param cdata <code>CDATA</code> to output.
- * @param out <code>Writer</code> to use.
- */
- protected void printCDATA(Writer out, CDATA cdata) throws IOException {
- String str = (currentFormat.mode == Format.TextMode.NORMALIZE)
- ? cdata.getTextNormalize()
- : ((currentFormat.mode == Format.TextMode.TRIM) ?
- cdata.getText().trim() : cdata.getText());
- out.write("<![CDATA[");
- out.write(str);
- out.write("]]>");
- }
-
- /**
- * This will handle printing of <code>{@link Text}</code> strings.
- *
- * @param text <code>Text</code> to write.
- * @param out <code>Writer</code> to use.
- */
- protected void printText(Writer out, Text text) throws IOException {
- String str = (currentFormat.mode == Format.TextMode.NORMALIZE)
- ? text.getTextNormalize()
- : ((currentFormat.mode == Format.TextMode.TRIM) ?
- text.getText().trim() : text.getText());
- out.write(escapeElementEntities(str));
- }
-
- /**
- * This will handle printing a string. Escapes the element entities,
- * trims interior whitespace, etc. if necessary.
- */
- private void printString(Writer out, String str) throws IOException {
- if (currentFormat.mode == Format.TextMode.NORMALIZE) {
- str = Text.normalizeString(str);
- }
- else if (currentFormat.mode == Format.TextMode.TRIM) {
- str = str.trim();
- }
- out.write(escapeElementEntities(str));
- }
-
- /**
- * This will handle printing of a <code>{@link Element}</code>,
- * its <code>{@link Attribute}</code>s, and all contained (child)
- * elements, etc.
- *
- * @param element <code>Element</code> to output.
- * @param out <code>Writer</code> to use.
- * @param level <code>int</code> level of indention.
- * @param namespaces <code>List</code> stack of Namespaces in scope.
- */
- protected void printElement(Writer out, Element element,
- int level, NamespaceStack namespaces)
- throws IOException {
-
- List attributes = element.getAttributes();
- List content = element.getContent();
-
- // Check for xml:space and adjust format settings
- String space = null;
- if (attributes != null) {
- space = element.getAttributeValue("space",
- Namespace.XML_NAMESPACE);
- }
-
- Format previousFormat = currentFormat;
-
- if ("default".equals(space)) {
- currentFormat = userFormat;
- }
- else if ("preserve".equals(space)) {
- currentFormat = preserveFormat;
- }
-
- // Print the beginning of the tag plus attributes and any
- // necessary namespace declarations
- out.write("<");
- printQualifiedName(out, element);
-
- // Mark our namespace starting point
- int previouslyDeclaredNamespaces = namespaces.size();
-
- // Print the element's namespace, if appropriate
- printElementNamespace(out, element, namespaces);
-
- // Print out additional namespace declarations
- printAdditionalNamespaces(out, element, namespaces);
-
- // Print out attributes
- if (attributes != null)
- printAttributes(out, attributes, element, namespaces);
-
- // Depending on the settings (newlines, textNormalize, etc), we may
- // or may not want to print all of the content, so determine the
- // index of the start of the content we're interested
- // in based on the current settings.
-
- int start = skipLeadingWhite(content, 0);
- int size = content.size();
- if (start >= size) {
- // Case content is empty or all insignificant whitespace
- if (currentFormat.expandEmptyElements) {
- out.write("></");
- printQualifiedName(out, element);
- out.write(">");
- }
- else {
- out.write(" />");
- }
- }
- else {
- out.write(">");
-
- // For a special case where the content is only CDATA
- // or Text we don't want to indent after the start or
- // before the end tag.
-
- if (nextNonText(content, start) < size) {
- // Case Mixed Content - normal indentation
- newline(out);
- printContentRange(out, content, start, size,
- level + 1, namespaces);
- newline(out);
- indent(out, level);
- }
- else {
- // Case all CDATA or Text - no indentation
- printTextRange(out, content, start, size);
- }
- out.write("</");
- printQualifiedName(out, element);
- out.write(">");
- }
-
- // remove declared namespaces from stack
- while (namespaces.size() > previouslyDeclaredNamespaces) {
- namespaces.pop();
- }
-
- // Restore our format settings
- currentFormat = previousFormat;
- }
-
- /**
- * This will handle printing of content within a given range.
- * The range to print is specified in typical Java fashion; the
- * starting index is inclusive, while the ending index is
- * exclusive.
- *
- * @param content <code>List</code> of content to output
- * @param start index of first content node (inclusive.
- * @param end index of last content node (exclusive).
- * @param out <code>Writer</code> to use.
- * @param level <code>int</code> level of indentation.
- * @param namespaces <code>List</code> stack of Namespaces in scope.
- */
- private void printContentRange(Writer out, List content,
- int start, int end, int level,
- NamespaceStack namespaces)
- throws IOException {
- boolean firstNode; // Flag for 1st node in content
- Object next; // Node we're about to print
- int first, index; // Indexes into the list of content
-
- index = start;
- while (index < end) {
- firstNode = (index == start) ? true : false;
- next = content.get(index);
-
- //
- // Handle consecutive CDATA, Text, and EntityRef nodes all at once
- //
- if ((next instanceof Text) || (next instanceof EntityRef)) {
- first = skipLeadingWhite(content, index);
- // Set index to next node for loop
- index = nextNonText(content, first);
-
- // If it's not all whitespace - print it!
- if (first < index) {
- if (!firstNode)
- newline(out);
- indent(out, level);
- printTextRange(out, content, first, index);
- }
- continue;
- }
-
- //
- // Handle other nodes
- //
- if (!firstNode) {
- newline(out);
- }
-
- indent(out, level);
-
- if (next instanceof Comment) {
- printComment(out, (Comment)next);
- }
- else if (next instanceof Element) {
- printElement(out, (Element)next, level, namespaces);
- }
- else if (next instanceof ProcessingInstruction) {
- printProcessingInstruction(out, (ProcessingInstruction)next);
- }
- else {
- // XXX if we get here then we have a illegal content, for
- // now we'll just ignore it (probably should throw
- // a exception)
- }
-
- index++;
- } /* while */
- }
-
- /**
- * This will handle printing of a sequence of <code>{@link CDATA}</code>
- * or <code>{@link Text}</code> nodes. It is an error to have any other
- * pass this method any other type of node.
- *
- * @param content <code>List</code> of content to output
- * @param start index of first content node (inclusive).
- * @param end index of last content node (exclusive).
- * @param out <code>Writer</code> to use.
- */
- private void printTextRange(Writer out, List content, int start, int end
- ) throws IOException {
- String previous; // Previous text printed
- Object node; // Next node to print
- String next; // Next text to print
-
- previous = null;
-
- // Remove leading whitespace-only nodes
- start = skipLeadingWhite(content, start);
-
- int size = content.size();
- if (start < size) {
- // And remove trialing whitespace-only nodes
- end = skipTrailingWhite(content, end);
-
- for (int i = start; i < end; i++) {
- node = content.get(i);
-
- // Get the unmangled version of the text
- // we are about to print
- if (node instanceof Text) {
- next = ((Text) node).getText();
- }
- else if (node instanceof EntityRef) {
- next = "&" + ((EntityRef) node).getValue() + ";";
- }
- else {
- throw new IllegalStateException("Should see only " +
- "CDATA, Text, or EntityRef");
- }
-
- // This may save a little time
- if (next == null || "".equals(next)) {
- continue;
- }
-
- // Determine if we need to pad the output (padding is
- // only need in trim or normalizing mode)
- if (previous != null) { // Not 1st node
- if (currentFormat.mode == Format.TextMode.NORMALIZE ||
- currentFormat.mode == Format.TextMode.TRIM) {
- if ((endsWithWhite(previous)) ||
- (startsWithWhite(next))) {
- out.write(" ");
- }
- }
- }
-
- // Print the node
- if (node instanceof CDATA) {
- printCDATA(out, (CDATA) node);
- }
- else if (node instanceof EntityRef) {
- printEntityRef(out, (EntityRef) node);
- }
- else {
- printString(out, next);
- }
-
- previous = next;
- }
- }
- }
-
- /**
- * This will handle printing of any needed <code>{@link Namespace}</code>
- * declarations.
- *
- * @param ns <code>Namespace</code> to print definition of
- * @param out <code>Writer</code> to use.
- */
- private void printNamespace(Writer out, Namespace ns,
- NamespaceStack namespaces)
- throws IOException {
- String prefix = ns.getPrefix();
- String uri = ns.getURI();
-
- // Already printed namespace decl?
- if (uri.equals(namespaces.getURI(prefix))) {
- return;
- }
-
- out.write(" xmlns");
- if (!prefix.equals("")) {
- out.write(":");
- out.write(prefix);
- }
- out.write("=\"");
- out.write(escapeAttributeEntities(uri));
- out.write("\"");
- namespaces.push(ns);
- }
-
- /**
- * This will handle printing of a <code>{@link Attribute}</code> list.
- *
- * @param attributes <code>List</code> of Attribute objcts
- * @param out <code>Writer</code> to use
- */
- protected void printAttributes(Writer out, List attributes, Element parent,
- NamespaceStack namespaces)
- throws IOException {
-
- // I do not yet handle the case where the same prefix maps to
- // two different URIs. For attributes on the same element
- // this is illegal; but as yet we don't throw an exception
- // if someone tries to do this
- // Set prefixes = new HashSet();
- for (int i = 0; i < attributes.size(); i++) {
- Attribute attribute = (Attribute) attributes.get(i);
- Namespace ns = attribute.getNamespace();
- if ((ns != Namespace.NO_NAMESPACE) &&
- (ns != Namespace.XML_NAMESPACE)) {
- printNamespace(out, ns, namespaces);
- }
-
- out.write(" ");
- printQualifiedName(out, attribute);
- out.write("=");
-
- out.write("\"");
- out.write(escapeAttributeEntities(attribute.getValue()));
- out.write("\"");
- }
- }
-
- private void printElementNamespace(Writer out, Element element,
- NamespaceStack namespaces)
- throws IOException {
- // Add namespace decl only if it's not the XML namespace and it's
- // not the NO_NAMESPACE with the prefix "" not yet mapped
- // (we do output xmlns="" if the "" prefix was already used and we
- // need to reclaim it for the NO_NAMESPACE)
- Namespace ns = element.getNamespace();
- if (ns == Namespace.XML_NAMESPACE) {
- return;
- }
- if ( !((ns == Namespace.NO_NAMESPACE) &&
- (namespaces.getURI("") == null))) {
- printNamespace(out, ns, namespaces);
- }
- }
-
- private void printAdditionalNamespaces(Writer out, Element element,
- NamespaceStack namespaces)
- throws IOException {
- List list = element.getAdditionalNamespaces();
- if (list != null) {
- for (int i = 0; i < list.size(); i++) {
- Namespace additional = (Namespace)list.get(i);
- printNamespace(out, additional, namespaces);
- }
- }
- }
-
- // * * * * * * * * * * Support methods * * * * * * * * * *
- // * * * * * * * * * * Support methods * * * * * * * * * *
-
- /**
- * This will print a newline only if indent is not null.
- *
- * @param out <code>Writer</code> to use
- */
- private void newline(Writer out) throws IOException {
- if (currentFormat.indent != null) {
- out.write(currentFormat.lineSeparator);
- }
- }
-
- /**
- * This will print indents only if indent is not null or the empty string.
- *
- * @param out <code>Writer</code> to use
- * @param level current indent level
- */
- private void indent(Writer out, int level) throws IOException {
- if (currentFormat.indent == null ||
- currentFormat.indent.equals("")) {
- return;
- }
-
- for (int i = 0; i < level; i++) {
- out.write(currentFormat.indent);
- }
- }
-
- // Returns the index of the first non-all-whitespace CDATA or Text,
- // index = content.size() is returned if content contains
- // all whitespace.
- // @param start index to begin search (inclusive)
- private int skipLeadingWhite(List content, int start) {
- if (start < 0) {
- start = 0;
- }
-
- int index = start;
- int size = content.size();
- if (currentFormat.mode == Format.TextMode.TRIM_FULL_WHITE
- || currentFormat.mode == Format.TextMode.NORMALIZE
- || currentFormat.mode == Format.TextMode.TRIM) {
- while (index < size) {
- if (!isAllWhitespace(content.get(index))) {
- return index;
- }
- index++;
- }
- }
- return index;
- }
-
- // Return the index + 1 of the last non-all-whitespace CDATA or
- // Text node, index < 0 is returned
- // if content contains all whitespace.
- // @param start index to begin search (exclusive)
- private int skipTrailingWhite(List content, int start) {
- int size = content.size();
- if (start > size) {
- start = size;
- }
-
- int index = start;
- if (currentFormat.mode == Format.TextMode.TRIM_FULL_WHITE
- || currentFormat.mode == Format.TextMode.NORMALIZE
- || currentFormat.mode == Format.TextMode.TRIM) {
- while (index >= 0) {
- if (!isAllWhitespace(content.get(index - 1)))
- break;
- --index;
- }
- }
- return index;
- }
-
- // Return the next non-CDATA, non-Text, or non-EntityRef node,
- // index = content.size() is returned if there is no more non-CDATA,
- // non-Text, or non-EntiryRef nodes
- // @param start index to begin search (inclusive)
- private static int nextNonText(List content, int start) {
- if (start < 0) {
- start = 0;
- }
-
- int index = start;
- int size = content.size();
- while (index < size) {
- Object node = content.get(index);
- if (!((node instanceof Text) || (node instanceof EntityRef))) {
- return index;
- }
- index++;
- }
- return size;
- }
-
- // Determine if a Object is all whitespace
- private boolean isAllWhitespace(Object obj) {
- String str = null;
-
- if (obj instanceof String) {
- str = (String) obj;
- }
- else if (obj instanceof Text) {
- str = ((Text) obj).getText();
- }
- else if (obj instanceof EntityRef) {
- return false;
- }
- else {
- return false;
- }
-
- for (int i = 0; i < str.length(); i++) {
- if (!Verifier.isXMLWhitespace(str.charAt(i)))
- return false;
- }
- return true;
- }
-
- // Determine if a string starts with a XML whitespace.
- private boolean startsWithWhite(String str) {
- if ((str != null) &&
- (str.length() > 0) &&
- Verifier.isXMLWhitespace(str.charAt(0))) {
- return true;
- }
- return false;
- }
-
- // Determine if a string ends with a XML whitespace.
- private boolean endsWithWhite(String str) {
- if ((str != null) &&
- (str.length() > 0) &&
- Verifier.isXMLWhitespace(str.charAt(str.length() - 1))) {
- return true;
- }
- return false;
- }
-
- /**
- * This will take the pre-defined entities in XML 1.0 and
- * convert their character representation to the appropriate
- * entity reference, suitable for XML attributes. It does not convert
- * the single quote (') because it's not necessary as the outputter
- * writes attributes surrounded by double-quotes.
- *
- * @param str <code>String</code> input to escape.
- * @return <code>String</code> with escaped content.
- */
- public String escapeAttributeEntities(String str) {
- StringBuffer buffer;
- char ch;
- String entity;
- EscapeStrategy strategy = currentFormat.escapeStrategy;
-
- buffer = null;
- for (int i = 0; i < str.length(); i++) {
- ch = str.charAt(i);
- switch(ch) {
- case '<' :
- entity = "<";
- break;
- case '>' :
- entity = ">";
- break;
- /*
- case '\'' :
- entity = "'";
- break;
- */
- case '\"' :
- entity = """;
- break;
- case '&' :
- entity = "&";
- break;
- case '\r' :
- entity = "
";
- break;
- case '\t' :
- entity = "	";
- break;
- case '\n' :
- entity = "
";
- break;
- default :
- if (strategy.shouldEscape(ch)) {
- entity = "&#x" + Integer.toHexString(ch) + ";";
- }
- else {
- entity = null;
- }
- break;
- }
- if (buffer == null) {
- if (entity != null) {
- // An entity occurred, so we'll have to use StringBuffer
- // (allocate room for it plus a few more entities).
- buffer = new StringBuffer(str.length() + 20);
- // Copy previous skipped characters and fall through
- // to pickup current character
- buffer.append(str.substring(0, i));
- buffer.append(entity);
- }
- }
- else {
- if (entity == null) {
- buffer.append(ch);
- }
- else {
- buffer.append(entity);
- }
- }
- }
-
- // If there were any entities, return the escaped characters
- // that we put in the StringBuffer. Otherwise, just return
- // the unmodified input string.
- return (buffer == null) ? str : buffer.toString();
- }
-
-
- /**
- * This will take the three pre-defined entities in XML 1.0
- * (used specifically in XML elements) and convert their character
- * representation to the appropriate entity reference, suitable for
- * XML element content.
- *
- * @param str <code>String</code> input to escape.
- * @return <code>String</code> with escaped content.
- */
- public String escapeElementEntities(String str) {
- if (escapeOutput == false) return str;
-
- StringBuffer buffer;
- char ch;
- String entity;
- EscapeStrategy strategy = currentFormat.escapeStrategy;
-
- buffer = null;
- for (int i = 0; i < str.length(); i++) {
- ch = str.charAt(i);
- switch(ch) {
- case '<' :
- entity = "<";
- break;
- case '>' :
- entity = ">";
- break;
- case '&' :
- entity = "&";
- break;
- case '\r' :
- entity = "
";
- break;
- case '\n' :
- entity = currentFormat.lineSeparator;
- break;
- default :
- if (strategy.shouldEscape(ch)) {
- entity = "&#x" + Integer.toHexString(ch) + ";";
- }
- else {
- entity = null;
- }
- break;
- }
- if (buffer == null) {
- if (entity != null) {
- // An entity occurred, so we'll have to use StringBuffer
- // (allocate room for it plus a few more entities).
- buffer = new StringBuffer(str.length() + 20);
- // Copy previous skipped characters and fall through
- // to pickup current character
- buffer.append(str.substring(0, i));
- buffer.append(entity);
- }
- }
- else {
- if (entity == null) {
- buffer.append(ch);
- }
- else {
- buffer.append(entity);
- }
- }
- }
-
- // If there were any entities, return the escaped characters
- // that we put in the StringBuffer. Otherwise, just return
- // the unmodified input string.
- return (buffer == null) ? str : buffer.toString();
- }
-
- /**
- * Returns a copy of this XMLOutputter.
- */
- public Object clone() {
- // Implementation notes: Since all state of an XMLOutputter is
- // embodied in simple private instance variables, Object.clone
- // can be used. Note that since Object.clone is totally
- // broken, we must catch an exception that will never be
- // thrown.
- try {
- return super.clone();
- }
- catch (java.lang.CloneNotSupportedException e) {
- // even though this should never ever happen, it's still
- // possible to fool Java into throwing a
- // CloneNotSupportedException. If that happens, we
- // shouldn't swallow it.
- throw new RuntimeException(e.toString());
- }
- }
-
- /**
- * Return a string listing of the settings for this
- * XMLOutputter instance.
- *
- * @return a string listing the settings for this XMLOutputter instance
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < userFormat.lineSeparator.length(); i++) {
- char ch = userFormat.lineSeparator.charAt(i);
- switch (ch) {
- case '\r': buffer.append("\\r");
- break;
- case '\n': buffer.append("\\n");
- break;
- case '\t': buffer.append("\\t");
- break;
- default: buffer.append("[" + ((int)ch) + "]");
- break;
- }
- }
-
- return (
- "XMLOutputter[omitDeclaration = " + userFormat.omitDeclaration + ", " +
- "encoding = " + userFormat.encoding + ", " +
- "omitEncoding = " + userFormat.omitEncoding + ", " +
- "indent = '" + userFormat.indent + "'" + ", " +
- "expandEmptyElements = " + userFormat.expandEmptyElements + ", " +
- "lineSeparator = '" + buffer.toString() + "', " +
- "textMode = " + userFormat.mode + "]"
- );
- }
-
- /**
- * Factory for making new NamespaceStack objects. The NamespaceStack
- * created is actually an inner class extending the package protected
- * NamespaceStack, as a way to make NamespaceStack "friendly" toward
- * subclassers.
- */
- private NamespaceStack createNamespaceStack() {
- // actually returns a XMLOutputter.NamespaceStack (see below)
- return new NamespaceStack();
- }
-
- /**
- * Our own null subclass of NamespaceStack. This plays a little
- * trick with Java access protection. We want subclasses of
- * XMLOutputter to be able to override protected methods that
- * declare a NamespaceStack parameter, but we don't want to
- * declare the parent NamespaceStack class as public.
- */
- protected class NamespaceStack
- extends org.jdom.output.NamespaceStack
- {
- }
-
- // Support method to print a name without using elt.getQualifiedName()
- // and thus avoiding a StringBuffer creation and memory churn
- private void printQualifiedName(Writer out, Element e) throws IOException {
- if (e.getNamespace().getPrefix().length() == 0) {
- out.write(e.getName());
- }
- else {
- out.write(e.getNamespace().getPrefix());
- out.write(':');
- out.write(e.getName());
- }
- }
-
- // Support method to print a name without using att.getQualifiedName()
- // and thus avoiding a StringBuffer creation and memory churn
- private void printQualifiedName(Writer out, Attribute a) throws IOException {
- String prefix = a.getNamespace().getPrefix();
- if ((prefix != null) && (!prefix.equals(""))) {
- out.write(prefix);
- out.write(':');
- out.write(a.getName());
- }
- else {
- out.write(a.getName());
- }
- }
-
- // * * * * * * * * * * Deprecated methods * * * * * * * * * *
-
- /* The methods below here are deprecations of protected methods. We
- * don't usually deprecate protected methods, so they're commented out.
- * They're left here in case this mass deprecation causes people trouble.
- * Since we're getting close to 1.0 it's actually better for people to
- * raise issues early though.
- */
-
- }
|