1

I am building a steam-clone game manager in Java and I am having problems with one final part of the project. On the left hand side of the GUI I have automatically populated "playlists" of games that are parsed from a library XML file, and I would like to retrieve the games from only that playlist when it is clicked on through a ListSelectionListener. I am currently able to populate ALL games stored in the library by using getElementsByTagName("Game"), but I need them to be specific to the playlist which is also assigned a unique id with an attributeID set to true for "Id".

However, in the below code, I need to do something like readLib.getElementById(id).getChildNodes(); but every time I do so I get a nullpointer exception at that line. Any ideas? I feel like I'm super close.

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); String[] gameArray = null;

    try {
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document readLib = builder.parse(LIBRARY_FILE_PATH);
        System.out.println("ID:" + id);
        NodeList gameNodes = readLib.getElementsByTagName("Game");
        gameArray = new String[gameNodes.getLength()];
        for (int i = 0; i < gameNodes.getLength(); i++) {
            Node p = gameNodes.item(i);
            if (p.getNodeType() == Node.ELEMENT_NODE) {
                Element Game = (Element) p;
                String gameNames = Game.getAttribute("Name");
                gameArray[i] = gameNames;
            }
        }
    } catch (ParserConfigurationException e) {
        LogToFile.writeFile("[GM-Logging] Parser configuratoin exception when generating game list");
    } catch (SAXException e) {
        LogToFile.writeFile("[GM-Logging] General SAXException in generateGames() method");
    } catch (IOException e) {
        LogToFile.writeFile("[GM-Logging] IOException while generating game names in Library Manager engine");
    }

This is an example of what the XML library looks like:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Library>
    <Playlist Id="0" list="First Person Shooters">
        <Game Name="Counter-Strike: Source">
            <Path>C:\\Program Files\\Games\\CSS\cstrike.exe</Path>
            <Executable>cstrike.exe</Executable>
        </Game>
        <Game Name="Counter-Strike: Global Offense">
            <Path>C:\\Program Files\\Games\\CSGO\csgo.exe</Path>
            <Executable>csgo.exe</Executable>
        </Game>
        <Game Name="Crysis 3">
            <Path>C:\\Program Files\\Games\\Crytek\crysislauncher.exe</Path>
            <Executable>crysislauncher.exe</Executable>
        </Game>
    </Playlist>
    <Playlist Id="1" list="Grand Theft Auto Series">
        <Game Name="Grand Theft Auto V">
            <Path>C:\\Program Files\\Games\\Rockstar\gtav.exe</Path>
            <Executable>gtav.exe</Executable>
        </Game>
        <Game Name="Grand Theft Auto IV: Ballad of Gay Tony">
            <Path>C:\\Program Files\\Games\\Rockstar\gtaiv\gtaiv.exe</Path>
            <Executable>gtaiv.exe</Executable>
        </Game>
    </Playlist>
<Playlist Id="2" list="Survival and Horror Games"></Playlist>

Nati0n
  • 25
  • 1
  • 5

2 Answers2

0

Looking at your xml, below is my suggestion.

create a class,

@XmlRootElement(name = "Library")
public class Library {
    private List<Playlist> playlist = new ArrayList<Playlist>();

..... getter 

@XmlElement(name = "Playlist")
public void setPlaylist(List<Playlist> playlist) {
        this.playlist = playlist;
}


@XmlRootElement(name = "Playlist")
public class Playlist {

private Game game;
private String path;
private String executable;

@XmlElement(name = "path")
public void setPath(String path) {
        this.path = path;
}

... similarly write getter and setter for game & executable


}

@XmlRootElement(name = "Game")
public class Game {

private String name;

@XmlElement(name = "name")
public void setName(String name) {
        this.name = name;
}

... write getter


}

in your main class

JAXBContext jaxbContext = JAXBContext.newInstance(Library.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

String xmlStr = xmlString; // the entire xml as string
            InputStream is = new ByteArrayInputStream(xmlStr.getBytes());

            Library library = (Library) jaxbUnmarshaller.unmarshal(is);

            List<Playlist> playLst = library.getPlayList();

now you have playLst object which is parsed XML

Saurabh Jhunjhunwala
  • 2,832
  • 3
  • 29
  • 57
0

I'd suggest to look into xpath. That will help you get specific part of an XML especially when you have more complex filter than just id attribute later. I'm not a java guy, the following codes constructed based on this : How to read XML using XPath in Java :

DocumentBuilder builder = factory.newDocumentBuilder();
Document readLib = builder.parse(LIBRARY_FILE_PATH);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("//Playlist[@id='" + id + "']/Game");

System.out.println("ID:" + id);
NodeList gameNodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
//the rest can be the same code
.......

short explanation about xpath being used :

Above codes generate xpath expression that looks like this :

//Playlist[@id='certain_id']/Game
  • //Playlist : find <Playlist> elements anywhere in the XML document
  • [@id='certain_id'] : filter to return only those having id attribute equals "certain_id"
  • /Game : from each of <Playlist> element that satisfies above criterion, get child element <Game>
Community
  • 1
  • 1
har07
  • 88,338
  • 12
  • 84
  • 137