0

I have an xml as shown below.

<?xml version="1.0" encoding="utf-8"?>
<package date-created="11/4/2014" client-version="blah" system-version="blah">  
<description />
<system>
<language /> 
</system>
<res id="blah" name="name" path="path" type="F" mimeType="mimetype-blah">
 <description />
 <keywords />
 <resver id="1690047800" major="50" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
 <resver id="1690167421" major="68" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
 <resver id="1690176842" major="71" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
</res>
<res id="blah1" name="name1" path="path1" type="F" mimeType="mimetype-blah1">
 <description />
 <keywords />
 <resver id="1690145841" major="34" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
 <resver id="1690161885" major="64" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
 <resver id="1690165275" major="66" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
 <resver id="1690169108" major="69" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
 <resver id="1690175442" major="87" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
</res>
</package>

I want to delete all <resver> elements except for the one with highest "major" attribute value. For example above major="71" is highest in the first resver group and major="87" is the highest in second resver group. So overall output looks like this:

<?xml version="1.0" encoding="utf-8"?>
<package date-created="11/4/2014" client-version="blah" system-version="blah">  
<description />
<system>
 <language /> 
</system>
<res id="blah" name="name" path="path" type="F" mimeType="mimetype-blah">
<description />
<keywords />
 <resver id="1690176842" major="71" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
</res>
<res id="blah1" name="name1" path="path1" type="F" mimeType="mimetype-blah1">
 <description />
 <keywords />
 <resver id="1690175442" major="87" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
</res>
</package>

I thought of using JAXB to do the work. Is there a better way to solve this? Can this be done with Simple Java File api?

Answer
I have written this thing using JAXB to acheive this. Here is the code

      try {

        File file = new File(FILE);
        JAXBContext jaxbContext = JAXBContext.newInstance(Package.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        Package pack = (Package) jaxbUnmarshaller.unmarshal(file);
        if (pack.getRes() == null || pack.getRes().size() == 0) {
            System.out.println("Size zero - exit");
            return;
        }
        for (Package.Res res : pack.getRes()) {
            if (! (res.getResver().size() == 1)) {
                Short max = getMaxMajorVersion(res);
                List<Package.Res.Resver> resverList = removeNonMaxResver(res, max);
                for (Package.Res.Resver resver : resverList)
                    res.getResver().remove(resver);
            }
        }
        finalPack = pack;
    } catch (JAXBException e) {
        e.printStackTrace();
    }
    marshal();

Method: extractNonMaxResver

      private static List<Package.Res.Resver> removeNonMaxResver(
        Package.Res res, Short max) {
    List<Package.Res.Resver> resverList = new ArrayList<Package.Res.Resver>();
    for (Package.Res.Resver resver : res.getResver()) {
        if (resver.getMajor() != max)
            resverList.add(resver);
    }
    return resverList;
}

Method: getMaxMajorVersion

      private static Short getMaxMajorVersion(Package.Res res) {
    List<Short> list = new ArrayList<Short>();
    for (Package.Res.Resver resver : res.getResver()) {
        list.add(resver.getMajor());
    }
    Short max = Collections.max(list);
    System.out.println("Max: " + max);
    return max;
}

Method: marshal

     public static void marshal() {
    try {

        File file = new File(FILE_OUT);
        JAXBContext jaxbContext = JAXBContext.newInstance(Package.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        // output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                Boolean.TRUE);

        jaxbMarshaller.marshal(finalPack, file);
        jaxbMarshaller.marshal(finalPack, System.out);

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

}
A.K
  • 37
  • 6

2 Answers2

0

You need to load the XML into either XMLElement or a Java object(using JAXB or other lib). If using XMLEement then you will be iterating through nodes and deleting as per your condition. and in case of Java Model object, just iterate through the list delete them and then persist the same Model as XML file. Go through the Java Docs :https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Element.html It has all API which you can use to manipulate XML.

ppuskar
  • 773
  • 6
  • 9
0

XML is not a programming language.

you cant add conditions on it, but the same is possible with processing languages such as XSLT.

<xsl:if test="@foo='bar'">
  <xsl:text>Hello, world!</xsl:text>
</xsl:if>

I suggest that as the best way to do this kind of operations.

Other possible operations are by parsing the XML String using basic String operations. Its complex and confusing and more error prone.

Ref This

Community
  • 1
  • 1
Dileep
  • 5,362
  • 3
  • 22
  • 38