4

I have the following xml file

<?xml version="1.0" encoding="UTF-8"?>
<Employees>
    <Employee ID="1">
        <Firstname>David</Firstname >
        <Lastname>Berkley</Lastname>
        <Age>30</Age>
        <Salary>25001</Salary>
    </Employee>
    <Employee ID="2">
        <Firstname>Ashton</Firstname>
        <Lastname>Hutt</Lastname>
        <Age>22</Age>
        <Salary>26000</Salary>
    </Employee>

</Employees>

I wish to add more fields in this XML file like :

1) New Employee.

2) New Employee Details like Address which is not present here.

3) Delete Previous record.

After taking the appropriate values from the user I may modify the XML accordingly through my java code.

Suppose after doing point number 1 and 2 my new xml becomes...

<?xml version="1.0" encoding="UTF-8"?>
<Employees>
    <Employee ID="1">
            <Firstname>David</Firstname >
            <Lastname>Berkley</Lastname>
            <Age>30</Age>
            <Salary>25001</Salary>
            <Address>10th cross,Park Avenue</Address>
        </Employee>
        <Employee ID="2">
            <Firstname>Ashton</Firstname>
            <Lastname>Hutt</Lastname>
            <Age>22</Age>
            <Salary>26000</Salary>
        </Employee>
    <Employee ID="3">
        <Firstname>Holly</Firstname>
        <Lastname>Becker</Lastname>
        <Age>24</Age>
        <Salary>30000</Salary>
    </Employee>

</Employees>

How can I achieve this Using the StAX parser? Please help me by giving some appropriate tips and code as to how I may achieve this. :(

EDIT 1

This is my function which I wish to call while adding any new record.

public void addNewEmployee(XMLStreamWriter writer,String newID, String firstN, String lastN, String age, String salary)
    {


         try 
         {


             writer.writeStartDocument();
             writer.writeStartElement("Employee");
             writer.writeAttribute("ID", newID);



             writer.writeStartElement("Firstname");
             writer.writeCharacters(firstN);
             writer.writeEndElement();

             writer.writeStartElement("Lastname");
             writer.writeCharacters(lastN);
             writer.writeEndElement();

             writer.writeStartElement("Age");
             writer.writeCharacters(age);
             writer.writeEndElement();

             writer.writeStartElement("Salary");
             writer.writeCharacters(salary);
             writer.writeEndElement();



             writer.writeEndElement();
             writer.writeEndDocument();


             writer.flush();
             writer.close();
            // System.out.println("New Record Added");

         } catch (XMLStreamException e) {
             e.printStackTrace();
         }


    }

EDIT 2 Another issue I am facing is while traversing the previous XML.... How can i traverse it so that my cursor goes right after this block

<Employee ID="2">
            <Firstname>Ashton</Firstname>
            <Lastname>Hutt</Lastname>
            <Age>22</Age>
            <Salary>26000</Salary>
        </Employee>

and before the line </Employees>

Because I need to call the addNewEmployee() at the proper moment.

DeepN
  • 344
  • 2
  • 13
  • 1
    Did you consider JAXB instead of StAX? It might be simpler: define the XSD, generate the JAXB classes, unmarshall the document, manipulate the list of employee objects, marshall the list again. – Puce Apr 21 '15 at 12:33
  • 1
    How far did you get with the StAX reader/ writer? Where do you have issues? – Puce Apr 21 '15 at 12:34
  • Well I have done with reading the data appropriately using StAX but when I am trying to write something most of the documents on the internet are using XMLStreamWriter . I wished to navigate through the XML file to add the details or modify them in its appropriate areas by checking the node details. But I am having a hard time finding out how......Well its a bit too late to shift to JAXB :( :( – DeepN Apr 21 '15 at 12:39
  • Please show us the relevant code what you have so far and tell us what the current result is. – Puce Apr 21 '15 at 12:41
  • @Puce : I have added one code snippet....tell me what you think and how I should approach.. – DeepN Apr 22 '15 at 06:42
  • Just one update: I am doing the above work by first storing all the XML data in one collection, modifying it accordingly and then writing the modified data in another XML and deleting the previous one. So, Finally it was not possible to modify my older XML file. So if anyone has any new updates or ideas do post it here. Thank you everyone for all the help. – DeepN Apr 29 '15 at 05:42
  • If you load all the data in memory first then you could overwrite the old XML file directly instead of creating a new file, deleting the old one and rename the new one. Just writing while reading can cause problems. Writing after reading should be fine however. – Puce Apr 29 '15 at 08:03
  • Is stax a requirement or you are open to something else? – vtd-xml-author Apr 20 '16 at 03:26

2 Answers2

2

You shouldn't create a new writer every time you call the method using the same file path as this will overwrite your file.

Create (and close) the writer only once and pass it as an argument to the method instead:

public void addNewEmployee(XMLStreamWriter writer, String newID, String firstN, String lastN, String age, String salary)
Puce
  • 37,247
  • 13
  • 80
  • 152
  • I tried to do it like you said. The old file is still getting deleted. – DeepN Apr 23 '15 at 06:30
  • 1
    @DeepN You will have to write to a new file and write out the elements you want to keep as well, I think. I don't think there is a way to modify the file at the same time you are reading it using StAX, but I might be wrong. – Puce Apr 23 '15 at 08:15
  • @DeepN Also consider to use the iterator API (event) instead of the cursor API (stream): https://docs.oracle.com/javase/tutorial/jaxp/stax/api.html – Puce Apr 23 '15 at 08:23
  • Indeed you should not read and write at the same stream simultaneously. You must write in a new ouptut. After parsing you can rename the file as you wish. – csauvanet Apr 23 '15 at 08:53
  • @Puce... I have updated my code snippet. Anyway...Are you saying that I have to create a new XML file everytime I need to append my older one??? – DeepN Apr 23 '15 at 09:04
  • @DeepN Yes, I think either that or read everything first into memory, manipulate it and then write it back to the original file. And as I said, I think using JAXB to this (read everything into memory) would be simpler. – Puce Apr 23 '15 at 09:16
  • @DeepN the writeStartDocument, writeEndDocument, close methods shoudn't be called inside this method (as you don't want to start and end the document everytime you call this method). The flush method call could be omitted probably, but shouldn't hurt. – Puce Apr 23 '15 at 09:40
  • @Puce.. I have removed that but still it is getting deleted. Can you tell me something about my EDIT #2 ? How do I traverse it properly? Can you give me one small code snippet for that part please :( That is I think the the main siurse of all the problems.. – DeepN Apr 24 '15 at 08:54
  • @DeepN I really think you should use either JAXB or at least the iterator API of StAX. With the cursor API of StAX this (copying elements from source to target) will be a lot of work, I think. Please update your code and sample code in the question to either JAXB or the iterator API and then tell us where you still have issues. – Puce Apr 24 '15 at 09:28
  • @Puce : It was not possible with iterator API. I have given one comment below my question about how I am doing it. Meanwhile I will start working with JAXB and learning it because I have not used that before. Anyway, Thank you for all the help and support. +1 for all the effort. – DeepN Apr 29 '15 at 05:45
1

I would point you to a new/novel way of doing what you described, by using VTD-XML... there are numerous reasons why VTD-XML is far better than all other solutions provided for this question... here are a few links ...

http://www.javaworld.com/article/2071745/soa/simplify-xml-processing-with-vtd-xml.html

http://www.devx.com/xml/Article/36379

http://sdiwc.net/digital-library/request.php?article=0d947fb50e2f0160a75ac9f6bbf0818a

import com.ximpleware.*;
import java.io.*;

public class simpleMod {
    public static void main(String s[]) throws VTDException,IOException{
        VTDGen vg = new VTDGen();
        if (!vg.parseFile("input.xml", false))
            return;
        VTDNav vn = vg.getNav();
        XMLModifier xm = new XMLModifier(vn);
        AutoPilot ap = new AutoPilot(vn),ap2=new AutoPilot(vn);
        ap.selectXPath("/employees/employee[@ID='1']/Salary");
        ap2.selectXPath("../../employee[@ID='2'");
        int i=ap.evalXPath();
        if (i==-1)
            return; 
        xm.insertAfterElement("<Address>10th cross, Park Avenue</Address>");
        i=ap2.evalXPath();
        if (i==-1)
            return;
        xm.insertAfterElement(" <Employee ID=\"3\">\n<Firstname>Holly</Firstname>\n<Lastname>Becker</Lastname>\n<Age>24</Age>\n<Salary>30000</Salary>\n</Employee>");
        xm.output("output.xml");

    }
}
vtd-xml-author
  • 3,319
  • 4
  • 22
  • 30