-1

I have a flat file of fixed length fields like this:

ITEM1234LED Light Set
ITEM1235Ratchet Tie 

I'd like to convert it into xml file:

<ITEMS>
  <ITEM>
    <ITEMID>1234</ITEMID>
    <DESCRIPTION>LED Light Set</DESCRIPTION>
  </ITEM>
  <ITEM>
    <ITEMID>1235</ITEMID>
    <DESCRIPTION>Ratchet Tie</DESCRIPTION>
  </ITEM>
</ITEMS>

Which is the best way to achieve this ?

Thank you.

Fred Smith
  • 73
  • 1
  • 8
  • what do you mean by best? – nandsito May 10 '17 at 13:55
  • 1
    Use maps and an XML library. – m0skit0 May 10 '17 at 13:55
  • Possible duplicate of [Simple Java to XML example](http://stackoverflow.com/questions/2867626/simple-java-to-xml-example) – f1sh May 10 '17 at 13:57
  • The best way to achieve this might be to look for other questions with the same problem. – f1sh May 10 '17 at 13:58
  • @f1sh Not a duplicate as that only covers part of the question. It's certainly relevant though. – Tim B May 10 '17 at 13:58
  • @TimB why not? Because it doesn't cover how to transform each line into a java object? – f1sh May 10 '17 at 14:04
  • @f1sh I already said why not. It only covers part of the question. The question has multiple parts, that is an excellent answer but to only one of those parts and leaves the other parts unanswered. – Tim B May 10 '17 at 14:11
  • @TimB I think it offers a very concrete and adaptable solution in the form of code. It has more substance than the two "answers" below. – f1sh May 10 '17 at 14:12
  • @f1sh Yes. It does. It has a good answer. I already said that. It's also not a duplicate. A duplicate means it fully answers the question. It doesn't. Hence not a duplicate. I'm not sure how this is complicated. My "answer" as you put it below may be brief (I'm not going to write the guy's code for him) but it gives him the overview of what he needs to do and points him in the direction of a library that he can use. That's enough for him to solve his problem. Your link is not as it completely ignores half of it. – Tim B May 10 '17 at 14:16

5 Answers5

1

You can use a simple XMLStreamWriter to create the XML document. No need to create a class for the records. Just extract the ID and the description as strings and push these strings to the XML. This works for large files, too. Neither the input file nor the XML document has to be hold entirely in memory.

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

public class Items {

  private static final int POS_ID = 4;
  private static final int POS_DESCR = 8;

  public static void main(String[] args) {
    // Files for input and output
    final Path inFile = Paths.get("items.txt");
    final Path outFile = Paths.get("items.xml");

    // Unfortunately, XMLStreamWriter doesn't implement AutoCloseable, 
    // so we cannot use it with try-with-resources.
    XMLStreamWriter xmlWriter = null;
    try(
        // BufferedReader for the input file (assuming UTF-8 for the encoding)
        BufferedReader reader = Files.newBufferedReader(
          inFile, StandardCharsets.UTF_8);

        // BufferedOutputStream, so encoding is handled entirely by 
        // the XMLStreamWriter.
        OutputStream out = new BufferedOutputStream(
          Files.newOutputStream(outFile));
        ) 
    {
      // Use a XMLStreamWriter to create the XML document.
      xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(out);
      xmlWriter.writeStartDocument();
      xmlWriter.writeStartElement("ITEMS");
      String line;
      while((line = reader.readLine()) != null) {
        // Parse the input line with fixed length fields
        final String id = line.substring(POS_ID, POS_DESCR);
        final String descr = line.substring(POS_DESCR);
        xmlWriter.writeStartElement("ITEM");

        xmlWriter.writeStartElement("ITEMID");
        xmlWriter.writeCharacters(id);
        xmlWriter.writeEndElement(); // ITEMID

        xmlWriter.writeStartElement("DESCRIPTION");
        xmlWriter.writeCharacters(descr);
        xmlWriter.writeEndElement(); // DESCRIPTION

        xmlWriter.writeEndElement(); // ITEM
      }
      xmlWriter.writeEndElement(); // ITEMS
      xmlWriter.writeEndDocument();
    } catch (IOException | XMLStreamException | FactoryConfigurationError e) {
      e.printStackTrace();
    } finally {
      // Cleaning up
      if(xmlWriter != null) {
        try {
          xmlWriter.close();
        } catch (XMLStreamException e) {
          e.printStackTrace();
        }
      }
    }
  }
}
vanje
  • 10,180
  • 2
  • 31
  • 47
0

1) Create a Java class, that maps to the data in the flat file, for ex:

public class Item {
    private String itemId;
    private String description;

    /**
     * @return the itemId
     */
    public String getItemId() {
        return itemId;
    }

    /**
     * @param itemId the itemId to set
     */
    public void setItemId(String itemId) {
        this.itemId = itemId;
    }

    /**
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    /**
     * @param description the description to set
     */
    public void setDescription(String description) {
        this.description = description;
    }
}

2) Parse the flat file into a list of 'Items' (List of Item objects)

3) Use a good, lightweight framework like 'xStream' and use the appropriate method to serialize Java object to XML file. For example: xStream.toXml(Object obj, Writer out)

PS: This is just a standard way (using well tested frameworks and hence, not re-inventing the wheel), but not the optimal one. Optimally, for performance and less memory footprint, you can parse the flat file and write to a XML file at the same time.

bchetty
  • 2,231
  • 1
  • 19
  • 26
  • 1
    What if the file is huge ??? - you will use a lot of resources. Why not process record at a time or use a streaming interface – Bruce Martin May 10 '17 at 17:43
  • Yes, thats true (Check the 'PS' in my post). Based on the requirements, there are different ways of doing that. – bchetty May 11 '17 at 12:56
-1

Create java objects to represent your logical data structure.

Parse the flat file and generate the java objects.

Use an XML library (for example JAXB) to serialize that tree of java objects into a file.

Tim B
  • 40,716
  • 16
  • 83
  • 128
-1

You could use any of the following to achieve what you're trying:

JAXB
XSLT 

Or you could use this to read a CSV or a flat file and serialize to an XML (as shown in your question)

Hope this helps!

N00b Pr0grammer
  • 4,503
  • 5
  • 32
  • 46
-1

I think what bchetty mentioned is good, but you do not need ANY XML libraries to output XML.

  1. Parse the file into an Collection<> of objects, just like bchetty mentioned. You can use regex, or tools like ANTLR / CookCC / JFlex etc to do the parsing.
  2. Then you can just open a PrintWriter for the file.

PrintWriter out = new PrintWriter (file);

out.println ("<ITEMS>");

for (Item item : Items)
{
    out.println ("  <ITEM>");
    out.println ("    <ITEMID>" + item.getItemId() + "</ITEMID>");
    out.println ("    <DESCRIPTION>" + item.getDescription () + "</DESCRIPTION>");
    out.println ("  </ITEM>");
}

out.println ("</ITEMS>");
out.close ();

user1456982
  • 125
  • 6
  • 1
    What happens if the file contains `<`, `>` or `&` (any Xml character) - you will end up with invalid Xml. Much better to use a standard library that takes care of this for you – Bruce Martin May 10 '17 at 17:40
  • Nah, you can deal with those characters by writing a conversion tool, or add <![[CDATA etc directives in XML. Using those tools adds significant learning curve and slows performance. – user1456982 May 10 '17 at 20:49
  • @user1456982: You suggest heavy tools like ANTLR and JFlex to simply parse a flat file without any syntax but a light-weight build-in tool to create right-minded XML is too much? There is almost never a reason to not use a library to read and write structured data like XML or JSON. There are too many corner cases even for simple examples. – vanje May 10 '17 at 23:26
  • Of regex, JFlex, CookCC and ANTLR, only ANTLR is heavy weight. And my main point was not addressing how to parse. I was only addressing that writing XML can be far simpler. As for corner cases, there aren't that many. I have written XML / JSON Parser Writer myself. And given the input, there are probably not going to be complicated cases anyways. – user1456982 May 11 '17 at 21:43