Java >> Java tutorial >  >> Tag >> XML

Oprettelse af XML til tre lister over forskellige objekter ved hjælp af STAX Parser

Du kan bruge Declarative Stream Mapping (DSM) stream parsing-bibliotek til nemt at konvertere kompleks XML til java-klasse. Den bruger StAX til at parse XML.

Jeg springer over at få noter tag og tilføj et felt i class_x_object tags til demonstration.

Her er XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <notes />
    <category_alpha>
        <list_a>
            <class_a_object>
                <fieldA>A1</fieldA>
            </class_a_object>
            <class_a_object>
                <fieldA>A2</fieldA>
            </class_a_object>
            <class_a_object>
                <fieldA>A3</fieldA>
            </class_a_object>

        </list_a>
        <list_b>
            <class_b_object>
                <fieldB>B1</fieldB>
            </class_b_object>
            <class_b_object>
                <fieldB>B2</fieldB>
            </class_b_object>
            <class_b_object>
                <fieldB>B3</fieldB>
            </class_b_object>
        </list_b>
    </category_alpha>
    <category_beta>
        <class_c_object>
          <fieldC>C1</fieldC>
        </class_c_object>
        <class_c_object>
          <fieldC>C2</fieldC>
        </class_c_object>
        <class_c_object>
          <fieldC>C3</fieldC>
        </class_c_object>
    </category_beta>
</root>

Først og fremmest skal du definere tilknytningen mellem XML-data og dine klassefelter i yaml- eller JSON-format.

Her er kortlægningsdefinitionerne:

result:     
   type: object
   path: /root   
   fields:
     listOfA:
       type: array
       path: .*class_a_object  # path is regex
       fields:
          fieldOfA:
            path: fieldA
     listOfB:
       type: array
       path: .*class_b_object
       fields:
          fieldOfB:
            path: fieldB 
     listOfC:
       type: array
       path: .*class_c_object
       fields:
          fieldOfC:
            path: fieldC 

Java-klasse, som du vil deserialisere:

public class Root {
    public List<A> listOfA;
    public List<B> listOfB;
    public List<C> listOfC;

    public static class A{
        public String fieldOfA;
    }
    public static class B{
        public String fieldOfB;
    }
    public static class C{
        public String fieldOfC;
    }

}   

Java-kode til at parse XML:

DSM dsm=new DSMBuilder(new File("path/to/mapping.yaml")).setType(DSMBuilder.TYPE.XML).create(Root.class);
Root root =  (Root)dsm.toObject(xmlFileContent);
// write root object as json
dsm.getObjectMapper().writerWithDefaultPrettyPrinter().writeValue(System.out, object);

Her er output:

{
  "listOfA" : [ {"fieldOfA" : "A1"}, {"fieldOfA" : "A2"}, {"fieldOfA" : "A3"} ],
  "listOfB" : [ {"fieldOfB" : "B1"}, {"fieldOfB" : "B2"}, "fieldOfB" : "B3"} ],
  "listOfC" : [ {"fieldOfC" : "C1"}, {"fieldOfC" : "C2"}, {"fieldOfC" : "C3"} ]
}

OPDATERING:

Som jeg forstår ud fra din kommentar, vil du gerne læse stor XML-fil som en stream. og behandle data, mens du læser filen.

DSM giver dig mulighed for at behandle data, mens du læser XML.

Deklarer tre forskellige funktioner til at behandle delvise data.

FunctionExecutor processA=new FunctionExecutor(){
            @Override
            public void execute(Params params) {

                Root.A object=params.getCurrentNode().toObject(Root.A.class);

                // process aClass; save to db. call service etc.
            }
        };
FunctionExecutor processB=new FunctionExecutor(){
            @Override
            public void execute(Params params) {

                Root.B object=params.getCurrentNode().toObject(Root.B.class);

                // process aClass; save to db. call service etc.
            }
        };

FunctionExecutor processC=new FunctionExecutor(){
            @Override
            public void execute(Params params) {

                Root.C object=params.getCurrentNode().toObject(Root.C.class);

                // process aClass; save to db. call service etc.
            }
        };

Registrer funktion til DSM

 DSMBuilder builder = new DSMBuilder(new File("path/to/mapping.yaml")).setType(DSMBuilder.TYPE.XML);

       // register function
        builder.registerFunction("processA",processA);
        builder.registerFunction("processB",processB);
        builder.registerFunction("processC",processC);

        DSM dsm= builder.create();
        Object object =  dsm.toObject(xmlContent);

ændre kortlægningsfilen til at kalde registreret funktion

result:     
   type: object
   path: /root   
   fields:
     listOfA:
       type: object
       function: processA  # when 'class_a_object' tag closed processA function will be executed.
       path: .*class_a_object  # path is regex
       fields:
          fieldOfA:
            path: fieldA
     listOfB:
       type: object
       path: .*class_b_object
       function: processB# register function
       fields:
          fieldOfB:
            path: fieldB 
     listOfC:
       type: object
       path: .*class_c_object
       function: processC# register function
       fields:
          fieldOfC:
            path: fieldC 

Du kan bruge Java Architecture til XML-binding til JAXB og Unmarshall ved at bruge POJO-klasserne som nævnt nedenfor.

Opret POJO-klasser først (jeg har taget nogle få noder fra din XML-fil og oprettet POJO. Du kan gøre det samme for resten). Nedenfor er den XML, jeg overvejede.

<?xml version="1.0" encoding="utf-8"?>
<root>
    <category_alpha>
        <list_a>
            <class_a_object></class_a_object>
            <class_a_object></class_a_object>
            <class_a_object></class_a_object>
            <class_a_object></class_a_object>
        </list_a>
        <list_b>
            <class_b_object></class_b_object>
            <class_b_object></class_b_object>
            <class_b_object></class_b_object>
            <class_b_object></class_b_object>
        </list_b>
    </category_alpha>
</root>

Nedenfor er POJO-klasserne for Root, category_alpha, list_a, list_b, class_a_object og class_b_object

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name = "root")
@XmlAccessorType (XmlAccessType.FIELD)
public class Root {

    @XmlElement(name = "category_alpha")
    private List<CategoryAlpha> categoryAlphaList = null;

    public List<CategoryAlpha> getCategoryAlphaList() {
        return categoryAlphaList;
    }

    public void setCategoryAlphaList(List<CategoryAlpha> categoryAlphaList) {
        this.categoryAlphaList = categoryAlphaList;
    }
}

Importer lignende java-importer til ovenstående klasse her i følgende klasser.

@XmlRootElement(name = "category_alpha")
@XmlAccessorType (XmlAccessType.FIELD)
public class CategoryAlpha {

    @XmlElement(name = "list_a")
    private List<ListAClass> list_a_collectionlist = null;

    @XmlElement(name = "list_b")
    private List<ListBClass> list_b_collectionlist = null;


    public List<ListAClass> getList_a_collectionlist() {
        return list_a_collectionlist;
    }


    public void setList_a_collectionlist(List<ListAClass> list_a_collectionlist) {
        this.list_a_collectionlist = list_a_collectionlist;
    }


    public List<ListBClass> getList_b_collectionlist() {
        return list_b_collectionlist;
    }


    public void setList_b_collectionlist(List<ListBClass> list_b_collectionlist) {
        this.list_b_collectionlist = list_b_collectionlist;
    }
}

@XmlRootElement(name = "list_a")
@XmlAccessorType (XmlAccessType.FIELD)
public class ListAClass {

    @XmlElement(name = "class_a_object")
    private List<ClassAObject> classAObjectList = null;

    public List<ClassAObject> getClassAObjectList() {
        return classAObjectList;
    }

    public void setClassAObjectList(List<ClassAObject> classAObjectList) {
        this.classAObjectList = classAObjectList;
    }
}

@XmlRootElement(name = "list_b")
@XmlAccessorType (XmlAccessType.FIELD)
public class ListBClass {

    @XmlElement(name = "class_b_object")
    private List<ClassBObject> classBObjectList = null;

    public List<ClassBObject> getClassBObjectList() {
        return classBObjectList;
    }

    public void setClassBObjectList(List<ClassBObject> classBObjectList) {
        this.classBObjectList = classBObjectList;
    }
}

@XmlRootElement(name = "class_a_object")
@XmlAccessorType (XmlAccessType.FIELD)
public class ClassAObject {

}

@XmlRootElement(name = "class_b_object")
@XmlAccessorType (XmlAccessType.FIELD)
public class ClassBObject {

}

Her er hovedklassen

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

public class UnmarshallMainClass {

    public static void main(String[] args) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        // This root object contains all the list of objects you are looking for
        Root emps = (Root) jaxbUnmarshaller.unmarshal( new File("sample.xml") );
    }

}

Ved at bruge gettere i rodobjektet og andre objekter kan du hente listen over alle objekter inde i roden på samme måde som nedenfor.

List<CategoryAlpha> categoryAlphaList = emps.getCategoryAlphaList();

Java tag