0

I have a sample XML of the format as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<Institutions>
    <Institution type = "School">
        <place>Munich</place>
        <Subjects>
            <Subject>English</Subject>
            <Subject>Deutsch</Subject>
        </Subjects> 
    </Institution>  
    <Institution type ="College">
        <place>Cologne</place>
        <Subjects>
            <Subject>Sports</Subject>
            <Subject>Gym</Subject>
        </Subjects> 
    </Institution>
    <Institution type= "University">
        <place>Hamburg</place>
        <Subjects>
            <Subject>MElectrical</Subject>
            <Subject>MComputers</Subject>
        </Subjects>
    </Institution>
</Institutions>

I have classes for Institutions and Institution as well

Institutions.java

import lombok.Data;
@XmlRootElement(name="Institutions")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class Institutions {
    public List<Institution> Institution;   
}

Institution.java

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Institution {

    @XmlAttribute(name = "type")
    private String type;
    
    @XmlElement(name = "place")
    private String place;
    
    @XmlElementWrapper(name="Subjects")   
    @XmlElement(name="Subject") 
    private List<String> subjects;
}

Now i have a main parser, whch takes care of the unmarshalling and marshalling. I want to add some more data to it, however this time, I want only the new added data in the newly produced XML.

For eg: I create a logic in the main

public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<Institutions> entries = new ArrayList<Institutions>();
    
        
        try {
            
            File xmlFile = new File("sample.xml");
            JAXBContext jaxbContext;
            jaxbContext = JAXBContext.newInstance(Institutions.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            Institutions xmlentries = (Institutions) jaxbUnmarshaller.unmarshal(xmlFile);
            entries.add(xmlentries);
            List<Institution> institutionList = xmlentries.getInstitution();
            Institution newInstitution = null;
            for(Institution i : institutionList) {
                if(i.getType().equals("School")) {
                    newInstitution = new Institution();
                    newInstitution.setPlace("Augsburg"); //(1)
                    newInstitution.setType("School");
                    List<String> subjectList = new ArrayList<String>();
                    subjectList.add("Math");
                    subjectList.add("Science");
                    newInstitution.setSubjects(subjectList);
                    break;
                }               
            }
            if(newInstitution!=null) {
                institutionList.add(newInstitution);
            }
Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(xmlentries, new File("outputsample.xml"));//(2)
            
        }catch (JAXBException e) {
            e.printStackTrace();
        } catch (FactoryConfigurationError e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }

Here I add a new entry based on the location of the school.

(1) can the entry field here be made generic/ based on te condition given. I do not want to type the school name again. (2) produces the XML, but how do I make sure that I have only the latest addition?

The current outputsample.xml looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Institutions>
    <Institution type="School">
        <place>Munich</place>
        <Subjects>
            <Subject>English</Subject>
            <Subject>Deutsch</Subject>
        </Subjects>
    </Institution>
    <Institution type="College">
        <place>Cologne</place>
        <Subjects>
            <Subject>Sports</Subject>
            <Subject>Gym</Subject>
        </Subjects>
    </Institution>
    <Institution type="University">
        <place>Hamburg</place>
        <Subjects>
            <Subject>MElectrical</Subject>
            <Subject>MComputers</Subject>
        </Subjects>
    </Institution>
    <Institution>
        <place>Augsburg</place>
        <Subjects>
            <Subject>Math</Subject>
            <Subject>Science</Subject>
        </Subjects>
    </Institution>
</Institutions>

But, i want the outputsample.xml to look like this ( all the added mdificaaitons

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Institutions>
    <Institution>
        <place>Augsburg</place>
        <Subjects>
            <Subject>Math</Subject>
            <Subject>Science</Subject>
        </Subjects>
    </Institution>
</Institutions>

Any guidnce here ? How could this be achieved? Also the aftermarshall cannot be applied within the main program? I need to eliminate the previously mentioned contents and keep the recently added ones

2 Answers 2

1

This would produce the output that you are looking for:

public class Main {
    public static void main(String[] args) throws JAXBException, XMLStreamException {
        final InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("sample.xml");
        final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
        final Unmarshaller unmarshaller = JAXBContext.newInstance(Root.class).createUnmarshaller();
        final Root root = unmarshaller.unmarshal(xmlStreamReader, Root.class).getValue();
        System.out.println(root.toString());

        Marshaller marshaller = JAXBContext.newInstance(Root.class).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(root, System.out);

        System.out.println();
        System.out.println(" ************************************** ");
        System.out.println();
        
        Institution newInstitution = new Institution();
        List<Institution> institutionList = root.getInstitution();
        for(Institution i : institutionList) {
            if(i.getType().equals("School")) {
                newInstitution = new Institution();
                newInstitution.setPlace("Augsburg"); //(1)
                newInstitution.setType("School");
                List<String> subjectList = new ArrayList<String>();
                subjectList.add("Math");
                subjectList.add("Science");
                newInstitution.setSubjects(subjectList);
                break;
            }
        }

        Marshaller newMarshaller = JAXBContext.newInstance(Institution.class).createMarshaller();
        newMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        QName qName = new QName("Institution");
        JAXBElement<Institution> newRoot = new JAXBElement<Institution>(qName, Institution.class, newInstitution);
        newMarshaller.marshal(newRoot, System.out);
    }
}

Output:

Root(Institution=[Institution(type=School, place=Munich, subjects=[English, Deutsch]), Institution(type=College, place=Cologne, subjects=[Sports, Gym]), Institution(type=University, place=Hamburg, subjects=[MElectrical, MComputers])])
<Institutions>
   <Institution type="School">
      <place>Munich</place>
      <Subjects>
         <Subject>English</Subject>
         <Subject>Deutsch</Subject>
      </Subjects>
   </Institution>
   <Institution type="College">
      <place>Cologne</place>
      <Subjects>
         <Subject>Sports</Subject>
         <Subject>Gym</Subject>
      </Subjects>
   </Institution>
   <Institution type="University">
      <place>Hamburg</place>
      <Subjects>
         <Subject>MElectrical</Subject>
         <Subject>MComputers</Subject>
      </Subjects>
   </Institution>
</Institutions>
 ************************************** 

<?xml version="1.0" encoding="UTF-8"?>
<Institution type="School">
   <place>Augsburg</place>
   <Subjects>
      <Subject>Math</Subject>
      <Subject>Science</Subject>
   </Subjects>
</Institution>
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you! I highly appreciate the feedback.. But changes can be done in the Main program itself? no need of aftermarshall?
If you are trying to create some different XML then aftermarshal is not a good choice. I was thinking you are adding something to the existing XML. Upvote it the answer helped you :)
I just did! thank you for the clarity. PHEW!
Also if I was adding to the same XML, could you suggest me the aftermarshal edit?
@RakshanPremsagarKapikad Added the answer: stackoverflow.com/a/68927608/7584240
|
1

Using the afterUnmarshal:

Your root class

@XmlRootElement(name = "Institutions")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class Root {
    public List<Institution> Institution;

    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) throws JAXBException {
        System.out.println("AFTER UNMARSHAL");
        Institution newInstitution = new Institution();
        List<Institution> institutionList = Institution;
        for (Institution i : institutionList) {
            if (i.getType().equals("School")) {
                newInstitution = new Institution();
                newInstitution.setPlace("Augsburg"); //(1)
                newInstitution.setType("School");
                List<String> subjectList = new ArrayList<String>();
                subjectList.add("Math");
                subjectList.add("Science");
                newInstitution.setSubjects(subjectList);
                break;
            }
        }

        Marshaller newMarshaller = JAXBContext.newInstance(Institution.class).createMarshaller();
        newMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        QName qName = new QName("Institution");
        JAXBElement<Institution> newRoot = new JAXBElement<Institution>(qName, Institution.class, newInstitution);
        newMarshaller.marshal(newRoot, System.out);
    }
}

Main:

public class Main {
    public static void main(String[] args) throws JAXBException, XMLStreamException {
        final InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("sample.xml");
        final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
        final Unmarshaller unmarshaller = JAXBContext.newInstance(Root.class).createUnmarshaller();
        final Root root = unmarshaller.unmarshal(xmlStreamReader, Root.class).getValue();
        System.out.println(root.toString());

        Marshaller marshaller = JAXBContext.newInstance(Root.class).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(root, System.out);
    }
}

Output:

AFTER UNMARSHAL
<?xml version="1.0" encoding="UTF-8"?>
<Institution type="School">
   <place>Augsburg</place>
   <Subjects>
      <Subject>Math</Subject>
      <Subject>Science</Subject>
   </Subjects>
</Institution>
Root(Institution=[Institution(type=School, place=Munich, subjects=[English, Deutsch]), Institution(type=College, place=Cologne, subjects=[Sports, Gym]), Institution(type=University, place=Hamburg, subjects=[MElectrical, MComputers])])
<Institutions>
   <Institution type="School">
      <place>Munich</place>
      <Subjects>
         <Subject>English</Subject>
         <Subject>Deutsch</Subject>
      </Subjects>
   </Institution>
   <Institution type="College">
      <place>Cologne</place>
      <Subjects>
         <Subject>Sports</Subject>
         <Subject>Gym</Subject>
      </Subjects>
   </Institution>
   <Institution type="University">
      <place>Hamburg</place>
      <Subjects>
         <Subject>MElectrical</Subject>
         <Subject>MComputers</Subject>
      </Subjects>
   </Institution>
</Institutions>

If you want to add to the same List: Root:

@XmlRootElement(name = "Institutions")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class Root {
    public List<Institution> Institution;

    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) throws JAXBException {
        Institution newInstitution = new Institution();
        newInstitution.setType("School");
        newInstitution.setPlace("Augsburg");
        newInstitution.setType("School");
        List<String> subjectList = new ArrayList<String>();
        subjectList.add("Math");
        subjectList.add("Science");
        newInstitution.setSubjects(subjectList);
    }
}

Output:

Root(Institution=[Institution(type=School, place=Munich, subjects=[English, Deutsch]), Institution(type=College, place=Cologne, subjects=[Sports, Gym]), Institution(type=University, place=Hamburg, subjects=[MElectrical, MComputers])])
<Institutions>
   <Institution type="School">
      <place>Munich</place>
      <Subjects>
         <Subject>English</Subject>
         <Subject>Deutsch</Subject>
      </Subjects>
   </Institution>
   <Institution type="College">
      <place>Cologne</place>
      <Subjects>
         <Subject>Sports</Subject>
         <Subject>Gym</Subject>
      </Subjects>
   </Institution>
   <Institution type="University">
      <place>Hamburg</place>
      <Subjects>
         <Subject>MElectrical</Subject>
         <Subject>MComputers</Subject>
      </Subjects>
   </Institution>
</Institutions>

1 Comment

Hi, could you look into stackoverflow.com/questions/69103790/… please

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.