Search code examples
javaxmlstax

Java Modify XML


I want to read an XML file in Java and then update certain elements in that file with new values. My file is > 200mb and performance is important, so the DOM model cannot be used.

I feel that a StaX Parser is the solution, but there is no decent literature on using Java StaX to read and then write XML back to the same file.

(For reference I have been using the java tutorial and this helpful tutorial to get what I have so far)

I am using Java 7, but there doesn't seem to be any updates to the XML parsing API since...a long time ago. So this probably isn't relevant.

Currently I have this:

public static String readValueFromXML(final File xmlFile, final String value) throws FileNotFoundException, XMLStreamException
{
    XMLEventReader reader = new XMLInputFactory.newFactory().createXMLEventReader(new FileReader(xmlFile));

    String found = "";
    boolean read = false;

    while (reader.hasNext())
    {
        XMLEvent event = reader.nextEvent();
        if (event.isStartElement() &&
            event.asStartElement().getName().getLocalPart().equals(value))
        {
            read = true;
        }

        if (event.isCharacters() && read)
        {
            found = event.asCharacters().getData();
            break;
        }
    }

    return found;
}

which will read the XMLFile and return the value of the selected element. However, I have another method updateXMLFile(final File xmlFile, final String value) which I want to use in conjunction with this.

So my question is threefold:

  1. Is there a StaX implementation for editing XML
  2. Will XPath be any help? Can that be used without converting my file to a Document?
  3. (More Generally) Why doesn't Java have a better XML API?

Solution

  • This is my approach, which reads events from the file using StaX and writes them to another file. The values are updated as the loop passes over the correctly named elements.

    public void read(String key, String value) 
        {
            try (FileReader fReader = new FileReader(inputFile); FileWriter fWriter = new FileWriter(outputFile))
            {
                XMLEventFactory factory = XMLEventFactory.newInstance();
                XMLEventReader reader = XMLInputFactory.newFactory().createXMLEventReader(fReader);
                XMLEventWriter writer = XMLOutputFactory.newFactory().createXMLEventWriter(fWriter);
    
                while (reader.hasNext())
                {
                    XMLEvent event = reader.nextEvent();
                    boolean update = false;
    
                    if (event.isStartElement() && event.asStartElement().getName().getLocalPart().equals(key))
                    {
                            update = true;
                    }
                    else if (event.isCharacters() && update)
                    {
                            Characters characters = factory.createCharacters(value);
                            event = characters;
                            update = false;
                    }
                    writer.add(event);
                }
            }
            catch (XMLStreamException | FactoryConfigurationError | IOException e)
            {
                e.printStackTrace();
            }
    
        }