1

There is a simple xml in the following format

<configuration>
<property>
  <name>crawling.depth</name>
  <value>1</value>
  <description/>
</property>

<property>
  <name>video.appid</name>
  <value>2</value>
  <description>Value modified @25-06-2014 11:37:28.731</description>
</property>
</configuration>

At start up of my application, I generate an id and set the same in the video.appid property of the XML.

I am using a simple DOM parser and the XML gets updated properly, but during repeated start up process, noticed that the space between the two properties is getting added. after five or so modifications, the file looks like the one below.

<configuration>
 <property>
  <name>crawling.depth</name>
  <value>1</value>
  <description/>
</property>







<property>
  <name>video.appid</name>
  <value>2</value>
  <description>Value modified @25-06-2014 12:30:18.125</description>
</property>
</configuration>

I remove the property and re-add the same into the XML, that I guess is the problem. while writing it back is there any way to reformat the whole file? so that the empty lines could be avoided.

tried googling it and got only indenting related info, which is not the problem here.

Thanks in advance.

Edit: Code which does the update:

public static boolean updatePropInFile(File file, Map propMap){
    boolean success = false;
    try {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        Document doc = docBuilder.parse(file);
        NodeList props = doc.getElementsByTagName("property");//No I18N
        List<Element> elements = new ArrayList<Element>();

        for(int i=0;i<props.getLength();i++){
            Element prop = (Element)props.item(i);
            Element nme = (Element)prop.getElementsByTagName("name").item(0);//No I18N
            String propName = nme.getTextContent();
            Iterator it = propMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry pairs = (Map.Entry)it.next();
                if(pairs.getKey().equals(propName)){
                    prop.getParentNode().removeChild(prop);                     
                    i--;
                }
            }
        }
        Iterator it = propMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry)it.next();
            elements.add(createPropertyElement(doc,String.valueOf(pairs.getKey()),String.valueOf(pairs.getValue())));
        }

        Node root = doc.getElementsByTagName("configuration").item(0);//No I18N
        for(Element ele:elements){
            root.appendChild(ele);
        }

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");//No I18N
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");//No I18N
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(file);
        transformer.transform(source, result);
        success=true;
    } catch (Exception pce) {
        success=false;
    }

    return success;
}
Alan Francis
  • 1,249
  • 11
  • 17
  • Who updates your xml? What you mean by startup? is it application startup or parser startup or server startup? It will be helpful if you post the code which updates the xml file. – AJJ Jun 25 '14 at 07:04
  • Try the setOutputProperty() of Transformer class and transform your xml doc using the transform. – AJJ Jun 25 '14 at 07:06
  • Please provide the code you used for XML parsing. – dARKpRINCE Jun 25 '14 at 07:21
  • edited the OP to include the code which modifies the XML. – Alan Francis Jun 25 '14 at 07:43
  • @AlanFrancis what does createPropertyElement() implement? and what are the values in propMap? – AJJ Jun 25 '14 at 09:25
  • possible duplicate of [How to remove extra empty lines from XML file?](http://stackoverflow.com/questions/12669686/how-to-remove-extra-empty-lines-from-xml-file) – dARKpRINCE Jun 25 '14 at 11:13

1 Answers1

2

Try this. Add the transformer to format your xml after modification.

public class ParseXml {

    public static void main(String[] args) {
        System.out.println("Started XML modification");
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder docBuilder = factory.newDocumentBuilder();

            Document xmlDoc;

            xmlDoc = docBuilder.parse(new File("sample.xml"));

            NodeList nodes = xmlDoc.getElementsByTagName("fr");

            for (int i = 0, length = nodes.getLength(); i < length; i ++) {
                ((Element)nodes.item(i)).setTextContent("Modified");
            }

            xmlDoc.getDocumentElement().normalize();
            TransformerFactory transformerFactory = TransformerFactory
                    .newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(
                    "{http://xml.apache.org/xslt}indent-amount", "4");
            DOMSource domSource = new DOMSource(xmlDoc);
            StreamResult result = new StreamResult(new File("sample.xml"));
            transformer.transform(domSource, result);
            System.out.println("Modification Done");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

Actual xml: Sample.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<titles>
    <tome>
       <de>DE1</de>
       <fr>Actual value</fr>
       <en>EN1</en>
    </tome>
    <valhalla>
       <de>DE2</de>
       <fr>Actual value</fr>
       <en>EN2</en>
    </valhalla>
    <vikings>
       <de>DE3</de>
       <fr>Actual value</fr>
       <en>EN3</en>
    </vikings>
</titles>

Output from the Java Class: Modified Xml: Sample.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<titles>
    <tome>
       <de>DE1</de>
       <fr>Modified</fr>
       <en>EN1</en>
    </tome>
    <valhalla>
       <de>DE2</de>
       <fr>Modified</fr>
       <en>EN2</en>
    </valhalla>
    <vikings>
       <de>DE3</de>
       <fr>Modified</fr>
       <en>EN3</en>
    </vikings>
</titles>

Update:

Not sure why you are getting white space in your formatted xml. Need to know what your createPropertyElement() does. For now you can use xsl to remove white spaces between parent tags,

TransformerFactory transformerFactory = TransformerFactory
                    .newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource("sample.xsl"));
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(
                    "{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource domSource = new DOMSource(xmlDoc);
StreamResult result = new StreamResult(new File("sample.xml"));
transformer.transform(domSource, result);

sample.xsl

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" omit-xml-declaration="yes" />

    <xsl:strip-space elements="*" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
AJJ
  • 3,570
  • 7
  • 43
  • 76
  • I have posted the code which does the update in OP, it already uses the transformer to format and indent. but the empty lines keep coming. – Alan Francis Jun 25 '14 at 07:39
  • @AlanFrancis added update to my answer. you can remove the white spaces in xml using the xsl stylesheets. – AJJ Jun 25 '14 at 09:49