Search code examples
javaxmlelementstax

Get element "text" by looking for it ID in XML (Stringtable for games) using StaX


So far I've got a way to SELECT the element I want by it´s ID but I tried and can't get a way to get It´s content (message).

public static String GetText(String id) throws FileNotFoundException, XMLStreamException
{
    File file = new File("C:/Users/LENOVO/IdeaProjects/CasinoRoyale/src/Stringtable.xml");

    // Instance of the class which helps on reading tags
    XMLInputFactory factory = XMLInputFactory.newInstance();

    // Initializing the handler to access the tags in the XML file
    XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(file));

    String text = "";

    // Checking the availability of the next tag
    while (eventReader.hasNext()) {
        XMLEvent xmlEvent = eventReader.nextEvent();
        Characters characters = xmlEvent.asCharacters();

        if (xmlEvent.isStartElement()) {
            StartElement startElement = xmlEvent.asStartElement();

            Iterator<Attribute> iterator = startElement.getAttributes();

            while (iterator.hasNext()) {
                Attribute attribute = iterator.next();
                QName name = attribute.getName();
                if ("id".equalsIgnoreCase(name.getLocalPart())) {

                    String currentId = String.valueOf(attribute.getValue());
                    if (currentId.equals(id))
                        text = characters.getData();
                    break;
                }
            }
        }
    }

    return text;

}

That's the method and It gives no error in the IDE so far.

<?xml version="1.0" encoding="UTF-8"?>
<Stringtable>
    <GameHelper id="welcomeTo">Welcome to Casino Royale!</GameHelper>

</Stringtable>

This is my short Stringtable.xml at the moment.

System.out.println(UtilitiesGame.GetText("welcomeTo"));

This is how I call it and it throws this Exception:

Exception in thread "main" java.lang.ClassCastException: class com.sun.xml.internal.stream.events.StartDocumentEvent cannot be cast to class javax.xml.stream.events.Characters (com.sun.xml.internal.stream.events.StartDocumentEvent and javax.xml.stream.events.Characters are in module java.xml of loader 'bootstrap') at java.xml/com.sun.xml.internal.stream.events.DummyEvent.asCharacters(DummyEvent.java:115) at UtilitiesGame.GetText(UtilitiesGame.java:66) at GameHelper.(GameHelper.java:67) at CasinoRoyale.main(CasinoRoyale.java:7)

What I want is that given ID (welcomeTo) I get "Welcome to Casino Royale!"


Solution

  • The exception is thrown because the event reader is still pointed to the startElement.

    You can easily fix it if you move the instanciation of the caracteres elements

    Characters characters = xmlEvent.asCharacters();
    

    Here the fix

    
        public static String GetText(String id) throws FileNotFoundException, XMLStreamException
        {    
            File file = new File("C:/Users/LENOVO/IdeaProjects/CasinoRoyale/src/Stringtable.xml");
    
            // Instance of the class which helps on reading tags
            XMLInputFactory factory = XMLInputFactory.newInstance();
    
            // Initializing the handler to access the tags in the XML file
            XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(file));
    
            String text = "";
    
            // Checking the availability of the next tag
            while (eventReader.hasNext()) {
                XMLEvent xmlEvent = eventReader.nextEvent();
    
                if (xmlEvent.isStartElement())
                {
                    // Characters characters = xmlEvent.asCharacters();
                    StartElement startElement = xmlEvent.asStartElement();
                    Iterator<Attribute> iterator = startElement.getAttributes();
                    while (iterator.hasNext())
                    {
                        Attribute attribute = iterator.next();
                        QName name = attribute.getName();
                        if ("id".equalsIgnoreCase(name.getLocalPart()))
                        {
                            String currentId = String.valueOf(attribute.getValue());
                            if (currentId.equals(id))
                            {
                                Characters characters = (Characters) eventReader.nextEvent();
                                text = characters.getData();
                            }
                            break;
                        }
                    }
                }
    
            }
            return text;
        }