简体   繁体   中英

How do you Marshal multiple sets of objects with different values in JAXB?

I'm trying to Marshal out tags in which the tags keep changing. I keep on overwriting the object values and end up with the same values for the tags when I Marshal.

Desired output:

<bookshelf>
  <shelfnumber> 001 </shelfnumber>
  <shelfowner> John Snow </shelfowner>
     <book>
        <Author>Ned Stark</Author>
        <Chapters>24</Chapters>
               <Chapter1>.......</Chapter1>
               <Chapter2>.......</Chapter2>
     </book>
     <book>

        <Author>Rob Stark</Author>
        <Chapters>24</Chapters>
               <Chapter1>.......</Chapter1>
               <Chapter2>.......</Chapter2>
     </book>
     <magazine>
        <Author>Tyrion Lannister</Author>
        <Pages>24</Pages>
               <Page1>.......</Page1>
               <Page2>.......</Page2>
     </magazine>    
</bookshelf>

I have a switch statement creating objects while iterating through an arraylist containing the extracted value from the database. I end up overwriting the last object so I am looking for a way to save a set of objects which are populated over each pass of my iterator.

public class TagFactory {
/*
 * Creates an arraylist from which to read the values and populate the tags
 */
private ArrayList<Data> Values;

public TagFactory(ArrayList<Data> values) {
    Values = values;

}

/*
 * Populates the Tran tags for the output based on the values in the Vales
 * arraylist. Uses the index of each cell to match up with the corresponding
 * tags
 */
public Tran TagPopulator() {

    BookShelf bookshelf = new BookShelf();
    Magazine mag = new Magazine();
    Book book = new book();
    Page page = new Page();
    Chapter chapter = new Chapter();


    /*
     * Create iterator and iterate though the extracted data arraylist
     */

    /*
     * Static Fields constructors
     */
    bookshelf.setNumber(BigInteger.valueOf(6));
    bookshelf.setAuthor("John Snow");
    ...

    Iterator<Data> ValuesIt = Values.iterator();

    boolean Endofchapter = false;
    boolean Endofpage = false;

    while (ValuesIt.hasNext()) {

        /*
         * Data object to hold the values
         */
        Data data = ValuesIt.next();

        /*
         * Select the appropriate class object constructor based on the
         * index of the cell This index was previously matched up in
         * HeaderValues and is used for a reference Type modification was
         * done for each of the constructor's requirements.
         */


        switch (data.getcellIndex()) {

        // Book->Author
        case 0:
            book.setAuthor(data.getcellValue());

            break;

        // Book->Chapter-> Chap #
        case 1:
            Chapter.add(data.getcellValue());
            ...
            Endofchapter = true;

            break;

        // Mag -> Author
        case 2:
            mag.setAuthor(data.getcellValue());
            break;

        // Mag->Page->Page#
        case 3:
            /*
             * Page object created and modified
             */
            page.setnum(data.getcellValue());

            Endofpage = true;
            break;

        ...
    if(Endofpage){
        mag.add(page);
    }
    if(Endofchapter){
        book.add(chapter);
    }
    bookshelf.add(mag);
    bookshelf.add(book)
...

I am marshaling after the loop has completed.

Added the Marshaling function

 public class XMLWriter {

    private String FileOutput;
    private Tran Transaction;
    ...

    public void FileOut () {
        try {
            /*
             * Marshal the classes into and XML output
             */
             File file = new File(FileOutput);
             JAXBContext JC = JAXBContext.newInstance(Tran.class);
             Marshaller JCMarshaller = JC.createMarshaller();

             JCMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

             JCMarshaller.marshal(Transaction, file);
             JCMarshaller.marshal(Transaction, System.out);

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

Added the call to the class for writing the XML.

XMLWriter output = new XMLWriter(outputFilename, newBookshelf.TagPopulator());
    output.FileOut();

All the objects Except the XMLWriter and TagFactory were produced by JAXB from a schema.

As we weren't shown the XML schema, the code below may not be an exact fit. It does, however, produce valid XML according to the XML sample. The List is replaced by a Scanner, reading from a text file. The intent of your while/switch isn't quite clear to me. There's no way I can imagine how these add() calls at the end might work correctly.

Note that it is not necessary to complete an object representing an element in the DOM tree before it is inserted into its parent. For repeated additions, keep a reference to the latest/current book or magazine.

There may be another way to determine the number of chapters and pages. I'm completely at a loss what should happen within a chapter or page.

    BookShelf bookshelf = new BookShelf();
    bookshelf.setShelfnumber( "001" );
    bookshelf.setShelfowner( "John Doe" );

    File f = new File( "data.txt" );
    Scanner scanner = new Scanner( f );
    Book book = null;
    Magazine magazine = null;
    int chapters = 0;
    int pages = 0;
    while( scanner.hasNext() ){
        int cellid = scanner.nextInt();
        switch(cellid){
        case 0:
            book = new Book();
            bookshelf.getBookOrMagazine().add( book );
            book.setAuthor( scanner.nextLine() );
            chapters = 0;
            break;
        case 1:
            Chapter chapter = new Chapter();
            book.getChapter().add( chapter );
            chapter.setNumber( scanner.nextInt() );
            book.setChapters( ++chapters );
            break;
        case 2:
            magazine = new Magazine();
            bookshelf.getBookOrMagazine().add( magazine );
            magazine.setAuthor( scanner.nextLine() );
            pages = 0;
            break;
        case 3:
            Page page = new Page();
            magazine.getPage().add( page );
            page.setNumber( scanner.nextInt() );
            magazine.setPages( ++pages );
            break;
        }
    }

The XML schema file I used:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        version="2.0">
<xs:element name="bookshelf" type="BookShelf"/>
<xs:complexType name="BookShelf">
  <xs:sequence>
    <xs:element name="shelfnumber" type="xs:string"/>
    <xs:element name="shelfowner"  type="xs:string"/>
    <xs:choice maxOccurs="unbounded">
      <xs:element name="book"     type="Book"/>
      <xs:element name="magazine" type="Magazine"/>
    </xs:choice>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="Book">
  <xs:sequence>
    <xs:element name="Author"   type="xs:string"/>
    <xs:element name="Chapters" type="xs:int"/>
    <xs:element name="chapter"  type="Chapter" maxOccurs="unbounded"/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="Magazine">
  <xs:sequence>
    <xs:element name="Author" type="xs:string"/>
    <xs:element name="Pages"  type="xs:int"/>
    <xs:element name="page"   type="Page" maxOccurs="unbounded"/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="Chapter">
  <xs:sequence>
    <xs:element name="number" type="xs:int"/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="Page">
  <xs:sequence>
    <xs:element name="number" type="xs:int"/>
  </xs:sequence>
</xs:complexType>
</xs:schema>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM