59

Currently our Java application uses the values held within a tab delimited *.cfg file. We need to change this application so that it now uses an XML file.

What is the best/simplest library to use in order to read in values from this file?

Jonik
  • 80,077
  • 70
  • 264
  • 372
rmcc
  • 3,507
  • 7
  • 29
  • 25

12 Answers12

57

There are of course a lot of good solutions based on what you need. If it is just configuration, you should have a look at Jakarta commons-configuration and commons-digester.

You could always use the standard JDK method of getting a document :

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

[...]

File file = new File("some/path");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(file);
Guillaume
  • 18,494
  • 8
  • 53
  • 74
  • 4
    Agreed. This is my preferred no-nonesense way of reading small XML files such as config files. Combine with XPath to make pulling out your config params less fussy. – Neil Coffey Jan 09 '09 at 21:58
  • 15
    You show nothing on how to read attributes and context. :( – chrisapotek Sep 11 '14 at 03:19
  • set feature secure processing to true to avoid XXE attacks: `DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);` – myhouse Aug 06 '19 at 19:06
37

XML Code:

<?xml version="1.0"?>
<company>
    <staff id="1001">
        <firstname>yong</firstname>
        <lastname>mook kim</lastname>
        <nickname>mkyong</nickname>
        <salary>100000</salary>
    </staff>
    <staff id="2001">
        <firstname>low</firstname>
        <lastname>yin fong</lastname>
        <nickname>fong fong</nickname>
        <salary>200000</salary>
    </staff>
</company>

Java Code:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;

public class ReadXMLFile {

  public static void main(String argv[]) {
    try {
    File fXmlFile = new File("/Users/mkyong/staff.xml");
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(fXmlFile);
    doc.getDocumentElement().normalize();

    System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
    NodeList nList = doc.getElementsByTagName("staff");
    System.out.println("----------------------------");

    for (int temp = 0; temp < nList.getLength(); temp++) {
        Node nNode = nList.item(temp);
        System.out.println("\nCurrent Element :" + nNode.getNodeName());
        if (nNode.getNodeType() == Node.ELEMENT_NODE) {
            Element eElement = (Element) nNode;
            System.out.println("Staff id : "
                               + eElement.getAttribute("id"));
            System.out.println("First Name : "
                               + eElement.getElementsByTagName("firstname")
                                 .item(0).getTextContent());
            System.out.println("Last Name : "
                               + eElement.getElementsByTagName("lastname")
                                 .item(0).getTextContent());
            System.out.println("Nick Name : "
                               + eElement.getElementsByTagName("nickname")
                                 .item(0).getTextContent());
            System.out.println("Salary : "
                               + eElement.getElementsByTagName("salary")
                                 .item(0).getTextContent());
        }
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
  }
}

Output:

----------------

Root element :company
----------------------------

Current Element :staff
Staff id : 1001
First Name : yong
Last Name : mook kim
Nick Name : mkyong
Salary : 100000

Current Element :staff
Staff id : 2001
First Name : low
Last Name : yin fong
Nick Name : fong fong
Salary : 200000

I recommended you reading this: Normalization in DOM parsing with java - how does it work?

Example source.

Community
  • 1
  • 1
Ran Adler
  • 3,587
  • 30
  • 27
  • I would say its best way to do it, you get more control on conversion and how you want to build objects, i tried dom4j but it failed because client was sending an unexpected namespace, which i was told earlier that we might send some unexpected fields or node in xml request. – Mubashar Jun 13 '14 at 03:06
  • 2
    +1 for actually showing how to read the data... the best answer does not. – chrisapotek Sep 11 '14 at 03:21
  • next time i will use JAXB – Ran Adler Mar 18 '15 at 07:09
  • 1
    I know this is old, but good god this is painful compared to reading XML files in C#. Is this really the best way to read XML data in Java? – Anonymous Sep 19 '18 at 08:52
  • this is definitely not the best way – Ran Adler Sep 20 '18 at 05:58
  • set feature secure processing to true to avoid XXE attacks: `DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);` – myhouse Aug 06 '19 at 19:03
11

What is the best/simplest library to use in order to read in values from this file?

As you're asking for the simplest library, I feel obliged to add an approach quite different to that in Guillaume's top-voted answer. (Of the other answers, sjbotha's JDOM mention is closest to what I suggest).

I've come to think that for XML handling in Java, using the standard JDK tools is certainly not the simplest way, and that only in some circumstances (such as not being able to use 3rd party libraries, for some reason) it is the best way.

Instead, consider using a good XML library, such as XOM. Here's how to read an XML file into a nu.xom.Document object:

import nu.xom.Builder;
import nu.xom.Document;
import java.io.File;

[...]

File file = new File("some/path");
Document document = new Builder().build(file);

So, this was just a little bit simpler, as reading the file into org.w3c.dom.Document wasn't very complicated either, in the "pure JDK" approach. But the advantages of using a good library only start here! Whatever you're doing with your XML, you'll often get away with much simpler solutions, and less of your own code to maintain, when using a library like XOM. As examples, consider this vs. this, or this vs. this, or this post containing both XOM and W3C DOM examples.

Others will provide counter-arguments (like these) for why sticking to Java's standard XML APIs may be worth it - these probably have merit, at least in some cases, although personally I don't subscribe to all of them. In any case, when choosing one way or the other, it's good to be aware of both sides of the story.

(This answer is part of my evaluation of XOM, which is a strong contender in my quest for finding the best Java XML library to replace dom4j.)

Community
  • 1
  • 1
Jonik
  • 80,077
  • 70
  • 264
  • 372
  • 2
    Oh, I agree with those who pointed out that XML may not necessarily be the best choice here at all, but for the purposes of this answer, I assumed that XML /is/ used – Jonik Jun 08 '09 at 06:31
8

Is there a particular reason you have chosen XML config files? I have done XML configs in the past, and they have often turned out to be more of a headache than anything else.

I guess the real question is whether using something like the Preferences API might work better in your situation.

Reasons to use the Preferences API over a roll-your-own XML solution:

  • Avoids typical XML ugliness (DocumentFactory, etc), along with avoiding 3rd party libraries to provide the XML backend

  • Built in support for default values (no special handling required for missing/corrupt/invalid entries)

  • No need to sanitize values for XML storage (CDATA wrapping, etc)

  • Guaranteed status of the backing store (no need to constantly write XML out to disk)

  • Backing store is configurable (file on disk, LDAP, etc.)

  • Multi-threaded access to all preferences for free

James Van Huis
  • 5,481
  • 1
  • 26
  • 25
4

JAXB is simple to use and is included in Java 6 SE. With JAXB, or other XML data binding such as Simple, you don't have to handle the XML yourself, most of the work is done by the library. The basic usage is to add annotation to your existing POJO. These annotation are then used to generate an XML Schema for you data and also when reading/writing your data from/to a file.

Pierre Buyle
  • 4,883
  • 2
  • 32
  • 31
3

I've only used jdom. It's pretty easy.

Go here for documentation and to download it: http://www.jdom.org/

If you have a very very large document then it's better not to read it all into memory, but use a SAX parser which calls your methods as it hits certain tags and attributes. You have to then create a state machine to deal with the incoming calls.

Sarel Botha
  • 12,419
  • 7
  • 54
  • 59
3

Look into JAXB.

cletus
  • 616,129
  • 168
  • 910
  • 942
1

The simplest by far will be Simple http://simple.sourceforge.net, you only need to annotate a single object like so

@Root
public class Entry {

   @Attribute
   private String a
   @Attribute
   private int b;
   @Element
   private Date c;

   public String getSomething() {
      return a;
   }
} 

@Root
public class Configuration {

   @ElementList(inline=true)
   private List<Entry> entries;

   public List<Entry> getEntries() { 
      return entries;
   }
}

Then all you have to do to read the whole file is specify the location and it will parse and populate the annotated POJO's. This will do all the type conversions and validation. You can also annotate for persister callbacks if required. Reading it can be done like so.

Serializer serializer = new Persister();
Configuration configuraiton = serializer.read(Configuration.class, fileLocation);
ng.
  • 7,099
  • 1
  • 38
  • 42
  • with xstream you dont have to annotate anything... – willcodejavaforfood Jan 09 '09 at 19:07
  • To tailor the XML schema you need to describe it, annotations are a perfectly valid means of doing this. JAXB, C# XML serialization, and even XStream have leveraged annotations to do this. We are not talking about serialization here we are talking about a structured XML schema mapped to an object. – ng. Jan 10 '09 at 00:38
1

Depending on your application and the scope of the cfg file, a properties file might be the easiest. Sure it isn't as elegant as xml but it certainly easier.

tmeisenh
  • 1,504
  • 1
  • 13
  • 11
1

Use java.beans.XMLDecoder, part of core Java SE since 1.4.

XMLDecoder input = new XMLDecoder(new FileInputStream("some/path.xml"));
MyConfig config = (MyConfig) input.readObject();
input.close();

It's easy to write the configuration files by hand, or use the corresponding XMLEncoder with some setup to write new objects at run-time.

erickson
  • 265,237
  • 58
  • 395
  • 493
0

This is what I use. http://marketmovers.blogspot.com/2014/02/the-easy-way-to-read-xml-in-java.html It sits on top of the standard JDK tools, so if it's missing some feature you can always use the JDK version.

This really makes things easier for me. It's especially nice when I'm reading a config file that was saved by and older version of the software, or was manually edited by a user. It's very robust and won't throw an exception if some data is not exactly in the format you expect.

Trade-Ideas Philip
  • 1,067
  • 12
  • 21
-1

Here's a really simple API that I created for reading simple XML files in Java. It's incredibly simple and easy to use. Hope it's useful for you.

http://argonrain.wordpress.com/2009/10/27/000/

Chris
  • 1