Eclipse XML Encoding
Hey everyone,
I've never used eclipse or java, and I have an assignment that is expected to use the XML encoding/decoding functionality. I've searched google a bit, but can't really find a good example. Does anyone have a link to some snippets or something that I could go by?
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
So I've made it somewhere with this ... but I'm stuck again. Here's what I have so far:
package main;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Shelf TestShelf = new Shelf("My Shelf");
Shelf TestShelf2 = new Shelf();
TestShelf.PrintProperties();
XMLEncoder e = new XMLEncoder(new BufferedOutputStream(
new FileOutputStream("Test.xml")));
e.writeObject(TestShelf);
e.writeObject(TestShelf2);
e.close();
XMLDecoder d = new XMLDecoder(new BufferedInputStream(
new FileInputStream("Test.xml")));
Object result = d.readObject();
System.out.println("Object: " + result);
result = d.readObject();
System.out.println("Object: " + result);
}
}
Which gives me this xml:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0" class="java.beans.XMLDecoder">
<object class="main.Shelf">
<void property="shelfID">
<int>0</int>
</void>
<void property="shelfName">
<string>My Shelf</string>
</void>
</object>
<object class="main.Shelf">
<void property="shelfID">
<int>1</int>
</void>
<void property="shelfName">
<string>New Shelf1</string>
</void>
</object>
</java>
And this output:
Shelf Name: My Shelf
Shelf ID: 0
Object: main.Shelf@169dd64
Object: main.Shelf@145f5e3
My question is, how can I extract exact values from my XML document? For example if I wanted to 'recreate' my saved XML session every time I load my program ... how can I access individual properties?
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
Object cast is required.
Shelf result =(Shelf) d.readObject();
System.out.println("Object: " + result.getShelfID() + " " + result.getShelfName());
>how can I extract exact values from my XML document?
Correct me if I'm wrong. I think there is no direct way to do so. What I'm telling you to read objects (Deserialize) from the XML document and push them into the ArrayList collection. What do you think about to serialize List?
__avd
Posting Genius (adatapost)
8,648 posts since Oct 2008
Reputation Points: 2,136
Solved Threads: 1,241
Oh ok, that makes a lot of sense. So when I write my save() method, I write my list of shelves to an xml file ... when I write my restore() method, I guess I could do like:
getNumberOfShelves()
for ( .... .... ....)
readXML() and setProperties()
Seems a little complex though - is there an easier way I'm not aware of?
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
ArrayLists are serialisable, so if you put all your Shelves into an ArrayList object you can write that to XML as a single object, and read it back with a single read. How simple is that?
JamesCherrill
Posting Genius
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
Oh very cool. So even though my Shelf will have Notebooks -> Notes, I can restore everything as long as I store the Shelves in a single ArrayList?
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
Yes, if all the individual classes can be serialised, then so can collections of them. Similarly if a class contains instances of another (serialisable) class it will serialise completely. I'm assuming Shelf, Notebook, Note are all serialisable?
JamesCherrill
Posting Genius
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
I'm not sure ... I'm pretty new to this. Do I just need to keep doing this:
public class Shelf implements java.io.Serializable
I honestly have no idea what java.io.Serializable does.
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
Its a "marker" interface - ithas no methods or anything, it just tells the compiler that the class is OK to serialise. I think its not actually needed for XML serialisation.As long as your classes all come down to simple things like ints and Strings in the end you'll be OK.
JamesCherrill
Posting Genius
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
So I'm at a bit of a road block. I'm trying to save my Session which consists of an ArrayList Shelf, which in turn contains an ArrayList Notebook.
I can save the Session, but the only thing written to the xml is the Shelf, not the Notebook contained within the shelf.
Here's my updated code:
package main;
import java.util.ArrayList;
public class Shelf implements java.io.Serializable {
public Shelf() {
shelfName = "New Shelf" + nextShelfID;
shelfID = nextShelfID;
nextShelfID++;
};
public Shelf(String name) {
shelfName = name;
shelfID = nextShelfID;
nextShelfID++;
};
private String shelfName;
static private int nextShelfID = 0;
private int shelfID;
public ArrayList<Notebook> notebooks = new ArrayList<Notebook>();
public void setShelfName(String name) {
shelfName = name;
}
public String getShelfName() {
return shelfName;
}
public int getShelfID() {
return shelfID;
}
public void setShelfID(int id) {
shelfID = id;
}
public int getNextShelfID() {
return nextShelfID;
}
public void PrintProperties() {
System.out.println("Shelf Name: " + shelfName);
System.out.println("Shelf ID: " + shelfID);
}
}
package main;
import java.util.ArrayList;
public class Notebook implements java.io.Serializable{
public Notebook() {
notebookName = "New Notebook" + nextNotebookID;
notebookID = nextNotebookID;
nextNotebookID++;
};
public Notebook(String name) {
notebookName = name;
notebookID = nextNotebookID;
nextNotebookID++;
};
private String notebookName;
static private int nextNotebookID = 0;
private int notebookID;
private ArrayList<Note> notes = new ArrayList<Note>();
public void setNotebookName(String name) {
notebookName = name;
}
public String getNotebookName() {
return notebookName;
}
public int getNotebookID() {
return notebookID;
}
public void setNotebookID(int id) {
notebookID = id;
}
public int getNextNotebookID() {
return nextNotebookID;
}
public void PrintProperties() {
System.out.println("Notebook Name: " + notebookName);
System.out.println("Notebook ID: " + notebookID);
}
}
public static void SaveActiveSession(ArrayList SessionToBeSaved)
throws FileNotFoundException {
XMLEncoder e = new XMLEncoder(new BufferedOutputStream(
new FileOutputStream("Test.xml")));
e.writeObject(SessionToBeSaved);
e.close();
}
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0" class="java.beans.XMLDecoder">
<object class="java.util.ArrayList">
<void method="add">
<object class="main.Shelf" id="Shelf0">
<void property="shelfID">
<int>0</int>
</void>
<void property="shelfName">
<string>New Shelf0</string>
</void>
</object>
</void>
</object>
</java>
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
XML encoder assumes your class conforms to the JavaBean style - ie get/set methods for all the attributes you need to serialise. YOu can write special code to handle more obscure problems http://java.sun.com/products/jfc/tsc/articles/persistence4/ but you shouldn't need anything like that for our classes. Just supply the missing get/set methods.
JamesCherrill
Posting Genius
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
My gets/sets are the same for both classes though, aren't they?
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
notebooks in the Shelf class doesn't have public get/set methods, so it doesn't get processed. You need something like
public ArrayList<Note> getNotebooks() {
return notebooks;
}
public void setNotebooks(ArrayList<Note> notebooks) {
this.notebooks= notebooks;
}
(and the same for notes in Notebook)
JamesCherrill
Posting Genius
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
Hm, still not writing out anything. Here's my Shelf class again, with the methods you suggested:
package main;
import java.util.ArrayList;
public class Shelf implements java.io.Serializable {
public Shelf() {
shelfName = "New Shelf" + nextShelfID;
shelfID = nextShelfID;
nextShelfID++;
};
public Shelf(String name) {
shelfName = name;
shelfID = nextShelfID;
nextShelfID++;
};
private String shelfName;
static private int nextShelfID = 0;
private int shelfID;
public ArrayList<Notebook> notebooks = new ArrayList<Notebook>();
public void setShelfName(String name) {
shelfName = name;
}
public ArrayList<Notebook> getNotebooks() {
return this.notebooks;
}
public void setNotebooks(ArrayList<Notebook> notebooks) {
this.notebooks = notebooks;
}
public String getShelfName() {
return shelfName;
}
public int getShelfID() {
return shelfID;
}
public void setShelfID(int id) {
shelfID = id;
}
public int getNextShelfID() {
return nextShelfID;
}
public void PrintProperties() {
System.out.println("Shelf Name: " + shelfName);
System.out.println("Shelf ID: " + shelfID);
}
}
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
Don't mix the definition of bean and list classes. Try to define a new list class.
For instance,
Foo.java
package main;
public class Foo
{
private int id;
private String name="";
public Foo() {}
public Foo(int id,String name) { this.id=id; this.name=name;}
public int getId() { return id;}
public String getName() { return name;}
public void setId(int id) { this.id=id;}
public void setName(String name) { this.name=name;}
}
FooList.java
package main;
import java.util.ArrayList;
public class FooList extends ArrayList<Foo>
{
public void add(int id,String name) {
super.add(new Foo(id,name));
}
public void show(){
for(Foo f:this)
System.out.println(f.getId() + " " + f.getName());
}
public Foo getById(int id){
for(Foo f:this)
{
if(f.getId()==id)
return f;
}
return null;
}
}
FooMain.java
package main;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class FooMain
{
public static void main(String []args)
{
FooList list=new FooList();
list.add(1,"A");
list.add(2,"B");
try{
XMLEncoder encode=new XMLEncoder(new BufferedOutputStream(
new FileOutputStream("Test.xml")));
encode.writeObject(list);
encode.close();
}catch(Exception ex){
ex.printStackTrace();
}
try{
XMLDecoder decode = new XMLDecoder(new BufferedInputStream(
new FileInputStream("Test.xml")));
FooList result = (FooList)decode.readObject();
decode.close();
result.show(); // print all objects
Foo f=result.getById(2); //Search by id
if(f!=null)
System.out.println(f.getId() + " "+ f.getName());
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
__avd
Posting Genius (adatapost)
8,648 posts since Oct 2008
Reputation Points: 2,136
Solved Threads: 1,241
Did you add the methods to the Notebook class as well?
JamesCherrill
Posting Genius
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
>Don't mix the definition of bean and list classes. Try to define a new list class.
That's not really an option at this point - is there any other way around this?
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
You don't have to create e new list class to use XML encoder, although there may be other design reasons why it would be a good idea.
Is this working yet? If not, perhaps you can post the complete current code, because there's no obvious reason why it won't work.
JamesCherrill
Posting Genius
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
The code is quite big at this point - however, I will post if absolutely necessary. As a general idea of what I'm trying to do, I have the following setup:
Notebook (class)
--- contains Array of Notes (class)
--- contains Array of Tags (class)
Note (class)
--- contains Array of Tags (class)
--- contains members (e.g., String for the note text)
Tag (class)
--- contains members (e.g., String for tag text)
So, I'd like to be able to save the Notebook to XML and also restore these objects if requested. As for naming and methods, is there anything other than getMember, setMember methods I need?
Duki
Nearly a Posting Virtuoso
1,475 posts since Jun 2006
Reputation Points: 817
Solved Threads: 32
Just public get/set for everything you want to write to XML, plus a public no-args constructor
JamesCherrill
Posting Genius
6,371 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073