Search code examples
javaxmliotddinputstream

How can I read XML data from inputStream object?


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?


Solution

  • 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