Responsive Ad Area
Home » Blog » XML Data Files: Reading and Writing XML data files using Java

Share This Post

Featured News / Featured Tutorials / Java / Tutorial

XML Data Files: Reading and Writing XML data files using Java

XML Data Files: Reading and Writing XML data files using Java

XML Data Files

In this post I will show you how to read and write data types in simple xml data files using XML DOM. DOM means Document Object Model. We are mainly concerned here with reading and writing some data of the same types we have been working with in previous articles. So i.e. xml data files

<some document>
 <some element>
  <some data name=value/>
  <some data name="value"/>
  <some data>
   some text
  </some data>
 </some element>
</some document>

XML Documents

XML document can be more complex with other parts to parse. In this, we have a document root which has as children
which have children which have attributes which contain the data we want to store. But also
text data can be stored if we use <some data> text </some data> notation.

The way this works we load the entire xml file into xml DOM document object. The we use methods to access the nodes in the DOM Tree. If you do not understand this terminology then research data structures and tree structures. The name=value pair is called an attribute of the element. So for our demo here I will choose a text based adventure game for the example.

<world>
 <room name="room name">
  <door aDirection="direction" room="room name">
  <brief description>
   Description text.
  </brief description>
  <description>
   Description text.
  </description>
  <items>
   <item name="item name">
    <description>
     description text
    </description>
   </item>
   <item name="item name"/>
    <description>
     description text
    </description>
   </item>
  </items>
 </room>
</world>

DTD

The above shows the format. Note that we could make a DTD Document Type Definition which defines how this XML document is formed. But it's not necessary if you are careful to form it properly in the first place. I have not made any DTDs myself and they do not seem easy to make. But if you used one then when the document is loaded into the DOM, if it did not conform to the DTD then you get errors and are told where they are so you can fix them from what I understand.

Our first example will not use I simply added that to show you that is something that might be needed to make a proper text-based adventure game. However simply making a world of rooms you can navigate is quite easy. Now, this example uses only one data type... String or text. A more complex example might use all the data types. So we will later create a better example to use all data types for some record type of storage.

Load Document

So we will load the document the and then get its children the and build a list of a class called Room probably put it in a class called World. Each Room object will contain fields for brief description and description. It will also contain a list of Door. A Door can be the cardinal directions of N, S, E, and W. And can be U or D for up or down. A door leads to another Room so it must also
contain that rooms name.

Needed are some commands in order to navigate the game world. Obviously, for navigation, we will use n,s,e,w,u and entered. So if we come back into the room only the brief description is shown. l would again show the long description. Or entering it for the first time shows long description. In this example, we will only be reading the XML file. In the later example of simple data records for all types, I will show reading, altering and writing the XML file.

So we will be looking for these types of DOM nodes. Document, Element, Attr, and Text.

 

To load the DOM we must..
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
we make a File object
we make a DocumentBuilderFactory object
we get a DocumentBuilder object from the factory.
we get a Document object from the DocmentBuilder parser method giving it the File object. 

Of course, we do this in a try/catch statement.

NodeList roomList = doc.getElementsByTagName("room"); will retrieve a list of all rooms in the world.

World data XML file

So below is the XML for our game world which describes rooms to navigate. Then I give you the code for loading the XML and playing
the text adventure at the windows shell console.

<world>
<room name="The Void" id="void">
<description>
You are standing in a dimly lit room that fades to darkness all around. In the center of the room is what looks like
some kind of doorway with swirling blueish light eliminating from its center outwards. As you walk around it you see it looks to
be somewhat translucent and not solid. Your hand can pass into and through it. Since there is nothing better to do I
recommend you enter and pass through the blue light doorway to see what happens.
</description>
<brief>
You are in a dark room with a blue colored translucent swirling doorway.
</brief>
<door dir="enter" room="forest"/>
</room>
<room name="Forest" id="forest">
<description>
This is a fairly thick forest of mixed evergreen and green leafed trees. There are a few large moss covered rocks around.
A very small trickling stream flows in from the north and out to the east. A game trail leads to the west and south. Also there is a blue swirling
lighted doorway here. I think you came through this and it is what is known as a portal. But should you ever try to go back through it?
</description>
<brief>
You are in a forest with a portal. There is a stream to the north and east and a trail to the west and south.
</brief>
<door dir="n" room=""/>
<door dir="s" room=""/>
<door dir="e" room=""/>
<door dir="w" room="cliffs"/>
<door dir="enter" room="void"/>
</room>
<room name="Large Cliffs" id="cliffs">
<description>
Trees disappear below a large cliff to the open skies to the west. A game trail emerges from thick forest to the east and seems to end but
you can navigate to the north and south along the cliffs bare rock. There is a large branch and log laying here that you have to
maneuver around. It overhangs the cliff a little. A blue berry bush is next to it. A blue portal is on the cliff to the north.
</description>
<brief>
You are standing on a large cliff next to an overhanging log. Paths lead north and south along the cliff
or into the woods to the east.
</brief>
<door dir="s" room="ridge"/>
<door dir="enter" room="island"/>
<door dir="e" room="forest"/>
</room>
<room name="Tropical Island" id="island">
<description>
Seagulls squawk and fly all around. Tropical palms and undergrowth are all around. In the center of this room is a blue portal.
White fluffy clouds mixed with deep blue skies are above. A cocoanut lies on the ground here. You can make out through the trees all around
what looks to be ocean water and waves. A rat scurries away. Paths are in all directions here.
</description>
<brief>
You are in the middle of a small tropical island with a blue portal. Paths are in all directions.
</brief>
<door dir="n" room="beach"/>
<door dir="s" room="beach"/>
<door dir="e" room="beach"/>
<door dir="w" room="beach"/>
<door dir="enter" room="cliffs"/>
</room>
<room name="Island Beach" id="beach">
<description>
You are standing on a sand/gravel beach. Ocean is out in front of you to the horizon. Tropical forest are behind you.
Small blue crabs are scattered all around. You see a starfish in the water. You also see sardines swimming about. A path
enters into the tropical forest behind you towards the center of the island. You can walk to the right or left along the
beach and around the island.
</description>
<brief>
You are standing on a beach. The ocean is in front of you and palm trees behind you. You may walk to the left or right along
the beach. A path enters the palms behind you back to the center of the island.
</brief>
<door dir="l" room="beach"/>
<door dir="r" room="beach"/>
<door dir="enter" room="island"/>
</room>
<room name="South End of Ridge" id="ridge">
<description>
This is the bottom of the downward slope at the end of a ridge. You can climb up the crest of the ridge to some cliffs above. Trees are
sparse here. There is a stand of tall cane that is very thick and you think you hear water running on the other side to the south. There
is a clearing to the west that looks like an open field. Woods to the east and slopes slightly upward. There is a crow in the tree above
and you hear it 'call' occasionally. An aluminum beer can refuse bottom shines in the penetrating sunbeams.
</description>
<brief>
Woods with river cane nearby. Clearing to the west. Woods to the east. Steep incline up the ridge to the north looks passable.
</brief>
<door dir="n" room="cliffs"/>
</room>
</world>

The Console Adventure Game

Below is the code for playing a text-based adventure at the windows shell console. This example is 230 lines of code. All
it does is allow you to enter a few commands and navigate some rooms with text descriptions. It demonstrates a few nice and good to know Java concepts in the process. If you examine the code you will see areas where refactoring needs to take place before this prototype is improved. Refactoring is where you take complex logic and either make new methods or you make new classes and new methods. Where code is long or repetitive it begins to smell of needing a refactoring. This was only a prototype so I kept it simple.

Java Scanner class

One important thing I showed you is how to use Scanner class to read input from the console. Its super simple. Another thing which was not as simple was to remove white space and new lines from Node text content. This demo does not show you how to convert different data types from strings. I am going to write a part 2 of this article to show you how to read and write some simple records using each data type as in previous examples. When you startup this app you are told to enter 'help' command to get a list of commands to use. You can try yourself to add a room into the game by adding one to the end of the xml file. Just use the other rooms as examples on how to build one. No recompile is necessary to add rooms. If you enter the xml wrong you will get a runtime exception. Some errors are more semantic in that you might put a room id name in the wrong place. Give it a try. Add a room called Pasture that is to the west of the end of the ridge. Or a pond in the woods to the east of the forest.

import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import javax.swing.*;

public class XMLReader{
public class Room{
public void cleanDescriptions(){
description = cleanString(description);
brief = cleanString(brief);
}
/** This cleans xml node text content strings */
String cleanString(String aString){
String[] lines = aString.split("\n");
StringBuilder sb = new StringBuilder();
for (String line : lines) {
sb.append(line.trim()+" ");
}
return sb.toString();
}
boolean visited=false;
String name="";
String id="";
String description="";
String brief="";
String n="";
String e="";
String s="";
String w="";
String enter="";
String l="";
String r="";
}
ArrayList<Room> rooms = new ArrayList<Room>();
public XMLReader(){
File adventureXMLFile = new File("adventure.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
String roomName="";
String doorDir="";
String doorRoomID="";
NodeList roomNodes = null;
NodeList roomChildNodes = null;
Room room = null;
Node roomNode = null;
Node roomChildNode = null;
Node AttributeNode = null;
NamedNodeMap Attributes = null;
try {
db = dbf.newDocumentBuilder();
Document doc = db.parse(adventureXMLFile);
roomNodes = doc.getElementsByTagName("room");
for (int i=0;i<roomNodes.getLength();i++){
roomNode = roomNodes.item(i);
room=new Room();
Attributes=roomNode.getAttributes();
AttributeNode=Attributes.getNamedItem("name");
room.name=AttributeNode.getNodeValue();
AttributeNode=Attributes.getNamedItem("id");
room.id=AttributeNode.getNodeValue();
roomChildNodes=roomNode.getChildNodes();
for(int c=0;c<roomChildNodes.getLength();c++){
roomChildNode=roomChildNodes.item(c);
if(roomChildNode.getNodeName().equals("description"))
room.description=roomChildNode.getTextContent();
else if(roomChildNode.getNodeName().equals("brief"))
room.brief=roomChildNode.getTextContent();
else if(roomChildNode.getNodeName().equals("door")){
Attributes=roomChildNode.getAttributes();
if(Attributes.getNamedItem("dir").getNodeValue().equals("n"))
room.n=Attributes.getNamedItem("room").getNodeValue();
if(Attributes.getNamedItem("dir").getNodeValue().equals("e"))
room.e=Attributes.getNamedItem("room").getNodeValue();
if(Attributes.getNamedItem("dir").getNodeValue().equals("s"))
room.s=Attributes.getNamedItem("room").getNodeValue();
if(Attributes.getNamedItem("dir").getNodeValue().equals("w"))
room.w=Attributes.getNamedItem("room").getNodeValue();
if(Attributes.getNamedItem("dir").getNodeValue().equals("enter"))
room.enter=Attributes.getNamedItem("room").getNodeValue();
if(Attributes.getNamedItem("dir").getNodeValue().equals("l"))
room.l=Attributes.getNamedItem("room").getNodeValue();
if(Attributes.getNamedItem("dir").getNodeValue().equals("r"))
room.r=Attributes.getNamedItem("room").getNodeValue();
}
}
room.cleanDescriptions();
rooms.add(room);
}
}catch(Exception e){
e.printStackTrace();
}
gameLoop();
}
void gameLoop(){
boolean hideBrief=true;
Scanner scan= new Scanner(System.in);
System.out.println("\nWelcome to the game Portals Adventure. If"+
"you need help just ask (by typing help command).\n");
String command="";
Room currentRoom = currentRoom=findRoom("void");
while(!command.equals("quit")){
if(currentRoom!=null)
if((currentRoom.visited==false)){
System.out.println("\n"+currentRoom.name+"\n");
System.out.println(currentRoom.description+"\n");
currentRoom.visited=true;
}else{if(!hideBrief){
System.out.println("\n"+currentRoom.name+"\n");
System.out.println(currentRoom.brief+"\n");
hideBrief=false;
}
}
System.out.println("What do you want to do?");
command= scan.nextLine();
if(command.equals("help")){
System.out.println("n goes north");
System.out.println("e goes east");
System.out.println("s goes south");
System.out.println("w goes west");
System.out.println("enter goes through portal or into something.");
System.out.println("l goes left");
System.out.println("r goes right");
System.out.println("look displays long description");
System.out.println("examine examines an item");
System.out.println("get item puts item in your backpack");
System.out.println("debug shows debug info about the current room");
System.out.println("quit exits to system");
}else if(command.equals("debug"))debugRoom(currentRoom);
else if(command.equals("enter")){
if(currentRoom.enter.equals("")){
System.out.println("\nThere is nothing to enter.\n");
hideBrief=true;
}else{
currentRoom=findRoom(currentRoom.enter);
if(currentRoom.visited)hideBrief=false;
}
continue;
}else if(command.equals("n")){
if(currentRoom.n.equals("")){
System.out.println("\nYou can't go that way.\n");
hideBrief=true;
}else{
currentRoom=findRoom(currentRoom.n);
if(currentRoom.visited)hideBrief=false;
}
continue;
}else if(command.equals("e")){
if(currentRoom.e.equals("")){
System.out.println("\nYou can't go that way.\n");
hideBrief=true;
}else{
currentRoom=findRoom(currentRoom.e);
if(currentRoom.visited)hideBrief=false;
}
continue;
}else if(command.equals("s")){
if(currentRoom.s.equals("")){
System.out.println("\nYou can't go that way.\n");
hideBrief=true;
}else{
currentRoom=findRoom(currentRoom.s);
if(currentRoom.visited)hideBrief=false;
}
continue;
}else if(command.equals("w")){
if(currentRoom.w.equals("")){
System.out.println("\nYou can't go that way.\n");
hideBrief=true;
}else{
currentRoom=findRoom(currentRoom.w);
if(currentRoom.visited)hideBrief=false;
}
continue;
}else if(command.equals("l")){
if(currentRoom.l.equals("")){
System.out.println("\nYou can't go that way.\n");
hideBrief=true;
}else{
currentRoom=findRoom(currentRoom.l);
if(currentRoom.visited)hideBrief=false;
}
continue;
}else if(command.equals("r")){
if(currentRoom.r.equals("")){
System.out.println("\nYou can't go that way.\n");
hideBrief=true;
}else{
currentRoom=findRoom(currentRoom.r);
if(currentRoom.visited)hideBrief=false;
}
continue;
}else if(command.equals("look")){
System.out.println("\n"+currentRoom.name+"\n");
System.out.println(currentRoom.description+"\n");
hideBrief=true;
continue;
}else if((command.length()>=7)&&(command.substring(0,7).equals("examine"))){
System.out.println("\nYou see nothing special about "+command.substring(8,command.length()));
hideBrief=true;
continue;
}else if((command.length()>=3)&&(command.substring(0,3).equals("get"))){
System.out.println("\nYou don't feel like carrying "+command.substring(4,command.length())+" today.");
hideBrief=true;
continue;
}else if(command.equals("quit")){
System.out.println("\nYes stop bingeing on text based adventure games and go get some stuff done. Goodbye!");
break;
}
System.out.println("\nWTF? I did not understand that command.");
}
}
Room findRoom(String id){
Iterator<Room> roomsIterator = rooms.iterator();
Room aRoom=null;
while(roomsIterator.hasNext()){
aRoom=roomsIterator.next();
if(aRoom.id.equals(id))return aRoom;
}
return null;
}
void debugRoom(Room aRoom){
System.out.println("Room Debug Info");
System.out.println("Name:"+aRoom.name);
System.out.println("Visited:"+aRoom.visited);
System.out.println("Description:"+aRoom.description);
System.out.println("Brief:"+aRoom.brief);
System.out.println("n:"+aRoom.n);
System.out.println("e:"+aRoom.e);
System.out.println("s:"+aRoom.s);
System.out.println("w:"+aRoom.w);
System.out.println("enter:"+aRoom.enter);
System.out.println("l:"+aRoom.l);
System.out.println("r:"+aRoom.r);
}
public static void main(String args[]){
new XMLReader();
}
}

 

Share This Post

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>