@@ -189,7 +189,7 @@ public boolean save(File file, String options) {
189189
190190
191191 public boolean save (PrintWriter output ) {
192- output .print (toString (2 ));
192+ output .print (format (2 ));
193193 output .flush ();
194194 return true ;
195195 }
@@ -756,20 +756,30 @@ public void setContent(String text) {
756756 }
757757
758758
759- public String toString (int indent ) {
759+ /**
760+ * Format this XML data as a String.
761+ * @param indent -1 for a single line (and no declaration), >= 0 for indents and newlines
762+ */
763+ public String format (int indent ) {
760764 try {
761- DOMSource dumSource = new DOMSource (node );
762765 // entities = doctype.getEntities()
763- TransformerFactory tf = TransformerFactory .newInstance ();
764- Transformer transformer = tf .newTransformer ();
765- // if this is the root, output the decl, if not, hide it
766+ TransformerFactory factory = TransformerFactory .newInstance ();
767+ if (indent != -1 ) {
768+ factory .setAttribute ("indent-number" , indent );
769+ }
770+ Transformer transformer = factory .newTransformer ();
771+
772+ // Add the XML declaration at the top if this node is the root and we're
773+ // not writing to a single line (indent = -1 means single line).
766774 if (indent == -1 || parent != null ) {
767775 transformer .setOutputProperty (OutputKeys .OMIT_XML_DECLARATION , "yes" );
768776 } else {
769777 transformer .setOutputProperty (OutputKeys .OMIT_XML_DECLARATION , "no" );
770778 }
771779// transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "sample.dtd");
780+
772781 transformer .setOutputProperty (OutputKeys .METHOD , "xml" );
782+
773783// transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "yes"); // huh?
774784
775785// transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
@@ -783,18 +793,45 @@ public String toString(int indent) {
783793// transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS
784794 // indent by default, but sometimes this needs to be turned off
785795 if (indent != 0 ) {
786- transformer .setOutputProperty ("{http://xml.apache.org/xslt}indent-amount" , String .valueOf (indent ));
796+ // transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(indent));
787797 transformer .setOutputProperty (OutputKeys .INDENT , "yes" );
798+ } else {
799+ transformer .setOutputProperty (OutputKeys .INDENT , "no" );
788800 }
789801// Properties p = transformer.getOutputProperties();
790802// for (Object key : p.keySet()) {
791803// System.out.println(key + " -> " + p.get(key));
792804// }
793805
794- StringWriter sw = new StringWriter ();
795- StreamResult sr = new StreamResult (sw );
796- transformer .transform (dumSource , sr );
797- return sw .toString ();
806+ // If you smell something, that's because this code stinks. No matter
807+ // the settings of the Transformer object, if the XML document already
808+ // has whitespace elements, it won't bother re-indenting/re-formatting.
809+ // So instead, transform the data once into a single line string.
810+ // If indent is -1, then we're done. Otherwise re-run and the settings
811+ // of the factory will kick in. If you know a better way to do this,
812+ // please contribute. I've wasted too much of my Sunday on it. But at
813+ // least the Giants are getting blown out by the Falcons.
814+
815+ StringWriter tempWriter = new StringWriter ();
816+ StreamResult tempResult = new StreamResult (tempWriter );
817+ transformer .transform (new DOMSource (node ), tempResult );
818+ String [] tempLines = PApplet .split (tempWriter .toString (), '\n' );
819+ if (tempLines [0 ].startsWith ("<?xml" )) {
820+ // Remove XML declaration from the top before slamming into one line
821+ tempLines = PApplet .subset (tempLines , 1 );
822+ }
823+ String singleLine = PApplet .join (PApplet .trim (tempLines ), "" );
824+ if (indent == -1 ) {
825+ return singleLine ;
826+ }
827+
828+ StringWriter stringWriter = new StringWriter ();
829+ StreamResult xmlOutput = new StreamResult (stringWriter );
830+ // DOMSource source = new DOMSource(node);
831+ Source source = new StreamSource (new StringReader (singleLine ));
832+ transformer .transform (source , xmlOutput );
833+ return stringWriter .toString ();
834+ // return xmlOutput.getWriter().toString();
798835
799836 } catch (Exception e ) {
800837 e .printStackTrace ();
@@ -803,9 +840,13 @@ public String toString(int indent) {
803840 }
804841
805842
843+ /**
844+ * Return the XML document formatted with two spaces for indents.
845+ * Chosen to do this since it's the most common case (e.g. with println()).
846+ * Same as format(2). Use the format() function for more options.
847+ */
806848 @ Override
807- /** Return the XML data as a single line, with no DOCTYPE declaration. */
808849 public String toString () {
809- return toString (- 1 );
850+ return format ( 2 );
810851 }
811852}
0 commit comments