Search code examples
javaxmlxml-parsingsaxsaxparser

Java creating a new xml file and appending it


I've developed a method which acquires a List collection with data needs to be written to an XML file. First of all I check the existence of the file, depending on the existence I either create a new file and write the data or append the data

I could not find out where the mistake is, I've checked the below links but I think I am far beyond the solution.

http://www.coderanch.com/t/561569/XML/Appending-data-existing-XML-file

It first created the file successfully there is no issue at that point, but when it does come to appending the file I do face the exception:

The markup in the document following the root element must be well-formed. Exception in createXMLFile org.xml.sax.SAXParseException; systemId:

Sample xml file is:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <text>
        <sentence>
            <word>data</word>
            <word>data1</word>
            <word>data2</word>
            <word>data3</word>
            <word>data4</word>
            <word>data5</word>
    </sentence>
</text>



protected boolean fileExists(String filePath) {
        if (new File(filePath).isFile())
            return new File(filePath).exists();
        return false;
    }

public File write(List<Sentence> sentenceData) {
        File file = null;
        try {
            final String fileName = getWorkingPath() + FileConstants.XML_FILE_NAME;
            boolean fileExist = fileExists(fileName);
            DocumentBuilderFactory docFactory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = null;
            if(fileExist)
                doc = docBuilder.parse(fileName);
            else
                doc = docBuilder.newDocument();
            // text element
            Element rootElement = doc.createElement("text");
            doc.appendChild(rootElement);

            // Iterate through sentence data
            ListIterator<Sentence> listIterator = sentenceData.listIterator();
            while (listIterator.hasNext()) {
                Sentence obj = (Sentence) listIterator.next();

                // sentence elements
                Element sentence = doc.createElement("sentence");
                rootElement.appendChild(sentence);

                // Iterate through words in the sentence
                for (String wordListData : obj.getWordList()) {
                    String wordData = wordListData;

                    // word elements in a sentence
                    Element word = doc.createElement("word");
                    word.appendChild(doc.createTextNode(wordData));
                    sentence.appendChild(word);
                }

                // remove the element
                listIterator.remove();
            }

            // write the content into xml file
            Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StreamResult result = new StreamResult(new FileWriter(fileName));
            DOMSource source = new DOMSource(doc);
            transformer.transform(source, result);

        } catch (ParserConfigurationException e) {
            logger.error("Exception in createXMLFile " + e);
        } catch (TransformerException e) {
            logger.error("Exception in createXMLFile " + e);
        } catch (SAXException e) {
            logger.error("Exception in createXMLFile " + e);
        } catch (IOException e) {
            logger.error("Exception in createXMLFile " + e);
        }
        return file;
    }

Edit: I've found out what I missed, and thrilled to put the answer here but I was late :) the below the full source code you may find. Hope it will help the others in the future.

public File write(List<Sentence> sentenceData) {
    final String fileName = getWorkingPath() + FileConstants.XML_FILE_NAME;
    final boolean fileExist = fileExists(fileName);
    File file = new File(fileName);

    try {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory
                .newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        Document doc = null;
        Element textElement = null;
        //Proceed depending on file existence
        if(fileExist){
            //File exists
            doc = docBuilder.parse(file);
            textElement = doc.getDocumentElement();
            // Iterate through sentence data
            ListIterator<Sentence> listIterator = sentenceData.listIterator();
            while (listIterator.hasNext()) {
                Sentence obj = (Sentence) listIterator.next();
                Element sentenceElement = doc.createElement("sentence");

                //Iterate through word list
                for(String word : obj.getWordList()){
                    Element wordElement = doc.createElement("word");
                    wordElement.appendChild(doc.createTextNode(word));
                    sentenceElement.appendChild(wordElement);
                }
                textElement.appendChild(sentenceElement);
            }
        }else{
            //File does not exist
            doc = docBuilder.newDocument();
            textElement = doc.createElement("text");
            doc.appendChild(textElement);
            // Iterate through sentence data
            ListIterator<Sentence> listIterator = sentenceData.listIterator();
            while (listIterator.hasNext()) {
                Sentence obj = (Sentence) listIterator.next();

                // sentence elements
                Element sentenceElement = doc.createElement("sentence");
                textElement.appendChild(sentenceElement);

                // Iterate through words in the sentence
                for (String wordListData : obj.getWordList()) {
                    String wordData = wordListData;

                    // word elements in a sentence
                    Element wordElement = doc.createElement("word");
                    wordElement.appendChild(doc.createTextNode(wordData));
                    sentenceElement.appendChild(wordElement);
                }
            }
        }

        Transformer transformer = TransformerFactory.newInstance()
                .newTransformer();
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(file);
        transformer.transform(source, result);
    } catch (ParserConfigurationException e) {
        logger.error("Exception in write " + e);
    } catch (SAXException e) {
        logger.error("Exception in write " + e);
    } catch (IOException e) {
        logger.error("Exception in write " + e);
    } catch (TransformerConfigurationException e) {
        logger.error("Exception in write " + e);
    } catch (TransformerFactoryConfigurationError e) {
        logger.error("Exception in write " + e);
    } catch (TransformerException e) {
        logger.error("Exception in write " + e);
    }

    return file;

}

Solution

  • I simulated your code here and did realized the you are not creating a valid root element in XML file, that's why you getting the exception.

    See my results that I am getting running the write method:

    public static void main(String... x) {
        Sentence s = new Sentence();
        Main m = new Main();
        List<Sentence> list = new ArrayList<Sentence>();
        list.add(s);
        m.write(list);
    }
    

    Sentence class:

    public class Sentence {
        public String[] getWordList() {
            return new String[] { "w4", "w5", "w6" }; // previous: w1,w2,w3
        }
    }
    

    file.xml:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <text>
        <sentence>
            <word>w1</word>
            <word>w2</word>
            <word>w3</word>
        </sentence>
        <sentence>
            <word>w4</word>
            <word>w5</word>
            <word>w6</word>
        </sentence>
        <sentence>
            <word>w4</word>
            <word>w5</word>
            <word>w6</word>
        </sentence>
    </text>
    

    Solution: Just replace your code with the following:

    // text element
    Element rootElement = null;
    if (!fileExist) {
        rootElement = doc.createElement("text");
        doc.appendChild(rootElement);
    } else {
        rootElement = doc.getDocumentElement(); // get the root [text] element
    }