java - Strange XML indentation -


i'm writing xml file, , tabbing coming out wrong :

<businessevents>  <mailevent>           <to>wellington</to>           <weight>10.0</weight>           <priority>air priority</priority>           <volume>10.0</volume>           <from>christchurch</from>           <day>mon may 20 14:30:08 nzst 2013</day>           <ppw>8.0</ppw>           <ppv>2.5</ppv>      </mailevent> <discontinueevent>           <to>wellington</to>           <priority>air priority</priority>           <company>kiwi co</company>           <from>sydney</from>      </discontinueevent> <routepriceupdateevent>           <weightcost>3.0</weightcost>           <to>wellington</to>           <duration>15.0</duration>           <maxweight>40.0</maxweight>           <maxvolume>20.0</maxvolume>           <priority>air priority</priority>           <company>kiwi co</company>           <day>mon may 20 14:30:08 nzst 2013</day>           <frequency>3.0</frequency>           <from>wellington</from>           <volumecost>2.0</volumecost>      </routepriceupdateevent> <customerpriceupdateevent>           <weightcost>3.0</weightcost>           <to>wellington</to>           <priority>air priority</priority>           <from>sydney</from>           <volumecost>2.0</volumecost>      </customerpriceupdateevent> </businessevents> 

as can see, first child node not indented @ all, nodes child indented twice? , close tag indented once?

i suspect might have adding root not document through doc.appendchild(root), when error

"an attempt made insert node not permitted. "

here parser:

documentbuilderfactory icfactory = documentbuilderfactory.newinstance();         documentbuilder icbuilder;         try {             icbuilder = icfactory.newdocumentbuilder();             string businesseventsfile = system.getproperty("user.dir") + "/testdata/businessevents/businessevents.xml";             document doc = icbuilder.parse (businesseventsfile);              element root = doc.getdocumentelement();              element element;              if(event instanceof customerpriceupdateevent){                 element = doc.createelement("customerpriceupdateevent");             }             else if(event instanceof discontinueevent){                 element = doc.createelement("discontinueevent");             }             else if(event instanceof mailevent){                 element = doc.createelement("mailevent");             }             else if(event instanceof routepriceupdateevent){                 element = doc.createelement("routepriceupdateevent");             }             else{                 throw new exception("business event isnt valid");             }              for(map.entry<string, string> field : event.getfields().entryset()){                 element newelement = doc.createelement(field.getkey());                 newelement.appendchild(doc.createtextnode(field.getvalue()));                 element.appendchild(newelement);             }              root.appendchild(element);               // output dom xml console             transformer transformer = transformerfactory.newinstance().newtransformer(); //            transformer.setoutputproperty(outputkeys.method, "xml");             transformer.setoutputproperty(outputkeys.indent, "yes");             transformer.setoutputproperty("{http://xml.apache.org/xslt}indent-amount", "5");             domsource source = new domsource(doc);             streamresult console = new streamresult(businesseventsfile);             transformer.transform(source, console); 

any insight appreciated.

i had same problem while ago. found out problem parsed document included white space text nodes on document.

for example, after parsing document, have blank text node right before <mailevent> node under <businessevents> node. transformer keeps blank text nodes (which assume correct behaviour).

so, if there no space @ between tags in xml text, transformer correctly indents tags. try code manually deleting whitespace, including line breaks, input, , format. output more expect.

one way solve remove redundant whitespace document after has been parsed. removing blank text nodes make formatting better, problem if of blank text nodes needed.

so did clean document before formatting remove text nodes containing whitespace, except cases text node child (no siblings).

the method cleanemptytextnodes(node parentnode) below recursively removes blank text nodes subtree.

import java.io.fileinputstream; import java.io.filenotfoundexception; import java.io.ioexception; import java.io.stringwriter;  import javax.xml.parsers.documentbuilder; import javax.xml.parsers.documentbuilderfactory; import javax.xml.parsers.parserconfigurationexception; import javax.xml.transform.outputkeys; import javax.xml.transform.transformer; import javax.xml.transform.transformerexception; import javax.xml.transform.transformerfactory; import javax.xml.transform.dom.domsource; import javax.xml.transform.stream.streamresult;  import org.w3c.dom.document; import org.w3c.dom.node; import org.xml.sax.saxexception;  public class formatxml {      public static void main(string[] args) throws parserconfigurationexception,             filenotfoundexception, saxexception, ioexception,             transformerexception {         documentbuilderfactory docbuilderfactory = documentbuilderfactory                 .newinstance();         documentbuilder documentbuilder = docbuilderfactory                 .newdocumentbuilder();         document node = documentbuilder.parse(new fileinputstream("data.xml"));         system.out.println(format(node, 4));     }      public static string format(node node, int indent)             throws transformerexception {         cleanemptytextnodes(node);         streamresult result = new streamresult(new stringwriter());         gettransformer(indent).transform(new domsource(node), result);         return result.getwriter().tostring();     }      private static transformer gettransformer(int indent) {         transformer transformer;         try {             transformer = transformerfactory.newinstance().newtransformer();         } catch (exception e) {             throw new runtimeexception("failed create transformer", e);         }         transformer.setoutputproperty(outputkeys.indent, "yes");         transformer.setoutputproperty(                 "{http://xml.apache.org/xslt}indent-amount",                 integer.tostring(indent));         return transformer;     }      /**      * removes text nodes contains whitespace. conditions      * removing text nodes, besides containing whitespace, are: if      * parent node has @ least 1 child of of following types,      * whitespace-only text-node children removed: - element child -      * cdata child - comment child      *       * purpose of make format() method (that use      * transformer formatting) more consistent regarding indenting , line      * breaks.      */     private static void cleanemptytextnodes(node parentnode) {         boolean removeemptytextnodes = false;         node childnode = parentnode.getfirstchild();         while (childnode != null) {             removeemptytextnodes |= checknodetypes(childnode);             childnode = childnode.getnextsibling();         }          if (removeemptytextnodes) {             removeemptytextnodes(parentnode);         }     }      private static void removeemptytextnodes(node parentnode) {         node childnode = parentnode.getfirstchild();         while (childnode != null) {             // grab "nextsibling" before child node removed             node nextchild = childnode.getnextsibling();              short nodetype = childnode.getnodetype();             if (nodetype == node.text_node) {                 boolean containsonlywhitespace = childnode.getnodevalue()                         .trim().isempty();                 if (containsonlywhitespace) {                     parentnode.removechild(childnode);                 }             }             childnode = nextchild;         }     }      private static boolean checknodetypes(node childnode) {         short nodetype = childnode.getnodetype();          if (nodetype == node.element_node) {             cleanemptytextnodes(childnode); // recurse subtree         }          if (nodetype == node.element_node                 || nodetype == node.cdata_section_node                 || nodetype == node.comment_node) {             return true;         } else {             return false;         }     }  } 

the resulting formatted output input:

<?xml version="1.0" encoding="utf-8" standalone="no"?> <businessevents>     <mailevent>         <to>wellington</to>         <weight>10.0</weight>         <priority>air priority</priority>         <volume>10.0</volume>         <from>christchurch</from>         <day>mon may 20 14:30:08 nzst 2013</day>         <ppw>8.0</ppw>         <ppv>2.5</ppv>     </mailevent>     <discontinueevent>         <to>wellington</to>         <priority>air priority</priority>         <company>kiwi co</company>         <from>sydney</from>     </discontinueevent>     <routepriceupdateevent>         <weightcost>3.0</weightcost>         <to>wellington</to>         <duration>15.0</duration>         <maxweight>40.0</maxweight>         <maxvolume>20.0</maxvolume>         <priority>air priority</priority>         <company>kiwi co</company>         <day>mon may 20 14:30:08 nzst 2013</day>         <frequency>3.0</frequency>         <from>wellington</from>         <volumecost>2.0</volumecost>     </routepriceupdateevent>     <customerpriceupdateevent>         <weightcost>3.0</weightcost>         <to>wellington</to>         <priority>air priority</priority>         <from>sydney</from>         <volumecost>2.0</volumecost>     </customerpriceupdateevent> </businessevents> 

Comments

Popular posts from this blog

.htaccess - First slash is removed after domain when entering a webpage in the browser -

Automatically create pages in phpfox -

c# - Farseer ContactListener is not working -