0

I am trying to create a Java program that finds the element (I am new to XML and don't understand the jargon. Is it even called an element?!?) whose value is highest and returns the element which surrounds it. Here is an example of the code:

<conversation input="HELLO">
    <output hits="3">
        HI MATE
    </output>
    <output hits="8">
        HELLO
    </output>
</conversation>

It would find which "output" has the most "hits" and return the value it contains (EX. HELLO). i am trying to use stAX but it you know of a better way to do this using something different, go right ahead!

EDIT Here is the requested full code:

package charles;

import java.io.FileNotFoundException;
import java.io.FileReader;
import javax.swing.JOptionPane;
import javax.xml.stream.*;
import javax.xml.stream.events.*;

public class NewClass {

    //Memory
    static String currentResult = null;
    static int highestHits = 0;
    private static String filename = "\\Files\\Java\\Projects\\CHARLES\\src\\charles\\Memory.xml";
    static XMLEventReader reader;

    public static void main(String args[]) throws XMLStreamException, FileNotFoundException {

        try {
            filename = "\\Files\\Java\\Projects\\CHARLES\\src\\charles\\Memory.xml";
        } catch (ArrayIndexOutOfBoundsException aioobe) {
            System.exit(0);
        }
        try {
            XMLInputFactory factory = XMLInputFactory.newInstance();
            XMLEventReader reader =
                    factory.createXMLEventReader(new FileReader(filename));
            while (reader.hasNext()) {
                XMLEvent e = reader.nextEvent();
                System.out.println("ID:" + e.hashCode() + "[" + e + "]");
            }
        } catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(null, "The file does not exist!" + "\nProgram is terminating.", "File Not Found", JOptionPane.INFORMATION_MESSAGE);
            System.exit(0);
        }

    }

    private static void analyze() {
        while (reader.hasNext()) {
            int event = (int) reader.next();
            if (event == XMLStreamConstants.START_ELEMENT && reader.getLocalName().equals(input)) {
                int currentHits = Integer.parseInt(reader.getAttributeValue(0));
                if (currentHits > highestHits) {
                    highestHits = currentHits;
                    reader.next();
                    currentResult = reader.getText();
                }
            }
        }

    }
}
Silver
  • 421
  • 2
  • 8
  • 17

2 Answers2

2

You could just use the java XML DOM classes to do this straightforwardly by passing over all the 'output' elements and recording which has the greatest 'hits' attribute. Say you have converted the XML to a DOM Document object 'doc', then you pass it to a method like this (returns null if there are no 'output' elements or if there are no non-zero hit attributes):

    public String getHighest(Document doc) {   
        NodeList list = doc.getElementsByTagName("output");
        String currentResult = null;
        int highestHit = 0;
        for (int i = 0; i < list.getLength(); i++) {
            int hits = Integer.parseInt(((Element) list.item(i)).getAttribute("hits"));
            if (hits > highestHit) {
                highestHit = hits;
                currentResult = list.item(i).getTextContent();
            }
         }
         return currentResult;
    }

This would only be appropriate if the XML document is not very large, as the DOM parser will load the whole of the XML tree into memory before it can be traversed. The parsed XML tree will typically take up 5 to 10 times more space than the XML in a file. So, if your XML file is larger than a few MB, you should use a SAX or StAX parser instead.

For StAX parsing this type of information, say you have an XMLStreamReader called 'reader', then the following snippet would work (though you should probably include some error-handling capability):

    int highestHits = 0;
    String currentResult = null;
    while (reader.hasNext()) {
        int event = reader.next();
        if (event == XMLStreamConstants.START_ELEMENT && reader.getLocalName().equals("output")) {
            int currentHits = Integer.parseInt(reader.getAttributeValue(0));
            if (currentHits > highestHits) {
                highestHits = currentHits;
                reader.next();
                currentResult = reader.getText();
            }
        }
    }

Edit re: updated code:

I think the problem is that in your code 'reader' is an XMLEventReader (well, the reason why it would not compile). But in 'analyze' you call methods on it that are from XMLStreamReader. Just make sure you use an XMLStreamReader to carry out the operations in the method 'analyze'.

lemonWorld
  • 221
  • 2
  • 12
  • Thanks for your help! the file will (hopefully) be very large so I will stick with stAX. I say hopefully due to the fact that, the bigger the file, the smarter my AI. – Silver Sep 24 '13 at 02:32
  • I ave run across a problem. When I put the code into netbeans (The stAX code), I run across the "cannot find symbol" error a lot for getLocalName, getAttributeName, and getText. Any idea on how to counter this? – Silver Sep 27 '13 at 00:54
  • 1
    Have you included the correct imports? As you can see from the XMLStreamReader API, http://docs.oracle.com/javase/7/docs/api/javax/xml/stream/XMLStreamReader.html, those methods are included. You should be able to call them on the 'reader' object. – lemonWorld Sep 27 '13 at 00:56
  • I believe so. I don't have to include any special libraries right? I included "import javax.xml.stream.*; import javax.xml.stream.events.*;" but that doesn't seem to help and netbeans hasn't suggested anything. Any ideas? – Silver Sep 27 '13 at 01:01
  • Not sure, would have to see the code. Maybe repost it here or in a new question? – lemonWorld Sep 27 '13 at 02:52
  • Well, it is quite a big code. I will create a little test file and try to post it up – Silver Sep 27 '13 at 02:58
  • You just need to post the relevant bits to the stax parsing, I think. – lemonWorld Sep 27 '13 at 03:00
  • I put the code into the previous question (So you could see it). Do you believe that i should as a new question regarding it? I think it is too trivial for that. Also you may see some weird notifications about and edit i accidentally made to your post. Ignore them ;) – Silver Sep 27 '13 at 03:10
0

I'd suggest using DOM and XPATH to solve this in the simples way.

Both of these should provide with some nice ideas on how this can be done: How to find the max attribute from an XML document using Xpath 1.0

How to read XML using XPath in Java

Community
  • 1
  • 1
trappski
  • 1,066
  • 10
  • 22