1

I have the following function which accept an InputStream object, and should read this stream and parse it's content into list<Transaction>

public void importTransactions(InputStream is) {
   
} 

On TDD, the test function gives me a case like this:

@Test
    public void givenValidXmlStream_WhenImport_ThenReturnTheExpectedTransactions() {
        InputStream is = asStream("<TransactionList>\n" +
                "    <Transaction type=\"C\" amount=\"1000\" narration=\"salary\" />\n" +
                "    <Transaction type=\"D\" amount=\"200\" narration=\"rent\" />\n" +
                "    <Transaction type=\"D\" amount=\"800\" narration=\"other\" />\n" +
                "</TransactionList>");
        xmlTransactionProcessor.importTransactions(is);
        List<Transaction> transactions = xmlTransactionProcessor.getImportedTransactions();

        assertThat(transactions, containsInAnyOrder(
                newTransaction("D", new BigDecimal(200), "rent"),
                newTransaction("C", new BigDecimal(1000), "salary"),
                newTransaction("D", new BigDecimal(800), "other")
        ));
    }

How should I implement this function? and how to read XML data from inputStream object?

Shahed A.
  • 17
  • 4
  • 1
    With [JAXB](https://www.oracle.com/technical-resources/articles/javase/jaxb.html) perhaps? "How should I parse XML" isn't a very straight-forward question to answer. – Kayaman Jun 27 '21 at 21:08
  • 2
    If you search for "How to parse XML in Java" you will find dozens of excellent answers to this question; I've chosen one of them rather arbitrarily as the answer. The subject is also well covered in online tutorials such as https://www.tutorialspoint.com/java_xml/index.htm, and in greater depth in books such as Elliotte Rusty Harold's. – Michael Kay Jun 27 '21 at 22:55

1 Answers1

1

As the comment suggested you can use JAXB. I tried to make a minimal example with the code you provided. I think from there you can improve the code yourself. The example is based on this guide.

Transaction class:

@XmlRootElement(name = "Transaction")
@XmlAccessorType(XmlAccessType.FIELD)
public class Transaction {

    @XmlAttribute(name = "type")
    private String type;
    @XmlAttribute(name = "amount")
    private BigDecimal amount;
    @XmlAttribute(name = "narration")
    private String narration;

    public Transaction() {
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    public String getNarration() {
        return narration;
    }

    public void setNarration(String narration) {
        this.narration = narration;
    }

TransactionList class:

@XmlRootElement(name = "TransactionList")
@XmlAccessorType(XmlAccessType.FIELD)
public class TransactionList {

    @XmlElement(name = "Transaction")
    private List<Transaction> transactions;

    public List<Transaction> getTransactions() {
        return transactions;
    }

    public void setTransactions(List<Transaction> transactions) {
        this.transactions = transactions;
    }
}

Main class:

public class XMLTest {

    public static List<Transaction> xmlToTransactionList(InputStream inputStream) throws JAXBException, ParserConfigurationException, SAXException {
        JAXBContext jaxbContext1 = JAXBContext.newInstance(TransactionList.class);

        Unmarshaller jaxbUnmarshaller = jaxbContext1.createUnmarshaller();

        TransactionList transactionList = (TransactionList) jaxbUnmarshaller.unmarshal(inputStream);

        return transactionList.getTransactions();
    }

    public static void main(String[] args) {
        String input = "<TransactionList>\n" +
                "    <Transaction type=\"C\" amount=\"1000\" narration=\"salary\" />\n" +
                "    <Transaction type=\"D\" amount=\"200\" narration=\"rent\" />\n" +
                "    <Transaction type=\"D\" amount=\"800\" narration=\"other\" />\n" +
                "</TransactionList>";
        InputStream stream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8));

        try {
            List<Transaction> transactions = xmlToTransactionList(stream);

            for (Transaction transaction : transactions) {
                System.out.println(transaction.getType() + " " + transaction.getAmount() + " " + transaction.getNarration());
            }

        } catch (JAXBException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }
    }
}

Output:

C 1000 salary
D 200 rent
D 800 other
JANO
  • 2,995
  • 2
  • 14
  • 29