javaxmljacksonxmlmapper

XmlMapper: read XML values without assigning a class for the created objects


I am trying to implement a multi language interface for my project and for this I want to load the data for the 3 languages from XML file. The problem is that when I want to read values I can only do it with readValue(file,MyClass.class) which I do not want because I want to extract directly data into a set and to iterate it, not into an object. In the XML file down, for example, I would like to extract directly the field with "english" and then to iterate through its values. The same I could do to "romanian" or "german". I find it useless to create a new class for every window I have... Is there a way to extract every language directly and to iterate trough its elements?

Here it is my XML code:

<?xml version="1.0" encoding="utf-8"?>
<langauges>
  <romanian>
    <flight_number>Numar zbor:</flight_number>
    <depart_airport>Aeroport plecare:</depart_airport>
    <destination>Destinatie:</destination>
    <flight_time>Timpul de zbor:</flight_time>
    <username>Utilizator:</username>
    <password>Parola:</password>
    <login>Log In</login>
    <search_depart_destination_time>Cautare dupa aeroport de plecare/destinatie si timp</search_depart_destination_time>
    <see_price_free_seats_2_locations>Vezi preturi si locuri libere intre 2 locatii</see_price_free_seats_2_locations>
    <search_after_flight_number>Cauta dupa numarul zborului</search_after_flight_number>
  </romanian>
  <english>
    <flight_number>Flight number:</flight_number>
    <depart_airport>Depart airport:</depart_airport>
    <destination>Destination:</destination>
    <flight_time>Flight time:</flight_time>
    <username>Username:</username>
    <password>Password:</password>
    <login>Log In</login>
    <search_depart_destination_time>Search after depart/destination airport and time</search_depart_destination_time>
    <see_price_free_seats_2_locations>See price and free seats between 2 locations</see_price_free_seats_2_locations>
    <search_after_flight_number>Search after flight number</search_after_flight_number>
  </english>
  <german>
    <flight_number>Flug Nummer:</flight_number>
    <depart_airport>Abflug flughafen:</depart_airport>
    <destination>Bestimmungsort:</destination>
    <flight_time>Flugzeit:</flight_time>
    <username>Nutzername:</username>
    <password>Passwort:</password>
    <login>Anmeldung</login>
    <search_depart_destination_time>Suchen zwischen abflug/bestimmungsort und zeit</search_depart_destination_time>
    <see_price_free_seats_2_locations>Sehen preis und frei plaetze zwischen 2 oerten</see_price_free_seats_2_locations>
    <search_after_flight_number>Suchen ueber Flug nummer</search_after_flight_number>
  </german>
</langauges>

Here, the Java method I unsuccessfully did:

XmlMapper xmlMapper = new XmlMapper();
File file = new File("languages.xml");
String xml = Files.readString(file.toPath());
String s =  xmlMapper.readValue(xml, String.class);

Solution

  • I think you may want an iterable structure which could be changed dynamically without changing your class too. In this case, I suggest using a map.

    Map<String, Map<String, String>>xmlMap = xmlMapper.readValue(xml, new TypeReference<Map<String, Map<String, String>>>() {});
    

    or simply

    Map<String, Map<String, String>>xmlMap = xmlMapper.readValue(xml, Map.class);
    

    but I prefer the previous one because it's cleaner. Then you could call them like

    String password = xmlMap.get("german").get("password");
    System.out.println(password);
    

    In other programming languages such as JavaScript, an object is simply a map and could be changed dynamically without too much effort.

    One scenario that I'm thinking about is to have a dropdown with the languages and after you choose it, you can iterate through the elements that are in that language, maybe you have a language that requires more or fewer fields, in this case, Map is a good choice.

    Hope it helped you!