使用 bindy 将 csv 转换为 xml

Convert csv to xml using bindy

我有这样的 csv:

31  name    2018-11-01  2018-10-31 12:05:16 3   
1   10  1.00    13.00       14  
2   20  1.00    14.00       14  
3   30  1.00    15.00       14  

一行中的字段由制表符分隔

接下来我还有另一行,也是分隔的制表符。每行以'\n'

分隔

我类应该是什么样子?

我做了这样的事情:

public class Order {

    private int id;
    private String name;
    private String date1;
    private int date2;
    private char numerOfFile;
    private List<OrderBody> orderBodyList;
}

public class OrderBody {

    private int lp;
    private int id;
    private BigDecimal priceByOne;
    private BigDecimal count;
    private int foreignId;
}

我建议使用 Groovy DSL 和 MarkupBuilder http://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html

def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.doubleQuotes = true
xml.mkp.xmlDeclaration(version: '1.0', encoding: 'foo-bar', and-so-on)

xml.orders(){
     'id':id,
     'name':name,
     ...         
    }
}
exchange.in.body = writer.toString()

使用以制表符作为分隔符的 FixedLengthRecord 模型的 camel-bindy 实际上是可能的。模型中的最后一个字段似乎需要一个长度,但其他字段可以使用制表符作为分隔符....

这是一个示例代码:

订单抬头:

import java.util.Date;

import org.apache.camel.dataformat.bindy.annotation.DataField;
import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;

@FixedLengthRecord()
public class OrderHeader {

    @DataField(pos = 1, delimiter = "\t")
    private int id;

    @DataField(pos = 2, delimiter = "\t")
    private String name;

    @DataField(pos = 3, delimiter = "\t", pattern = "yyyy-MM-dd")
    private Date date1;

    @DataField(pos = 4, delimiter = "\t", pattern = "yyyy-MM-dd hh:mm:ss")
    private Date date2;

    @DataField(pos = 5, length = 1)
    private int numerOfFile;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getDate1() {
        return date1;
    }

    public void setDate1(Date date1) {
        this.date1 = date1;
    }

    public Date getDate2() {
        return date2;
    }

    public void setDate2(Date date2) {
        this.date2 = date2;
    }

    public int getNumerOfFile() {
        return numerOfFile;
    }

    public void setNumerOfFile(int numerOfFile) {
        this.numerOfFile = numerOfFile;
    }

}

订单:

import java.math.BigDecimal;

import org.apache.camel.dataformat.bindy.annotation.DataField;
import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;

@FixedLengthRecord(header = OrderHeader.class)
public class Order {

    @DataField(pos = 1, delimiter = "\t")
    private int lp;

    @DataField(pos = 2, delimiter = "\t")
    private int id;

    @DataField(pos = 3, delimiter = "\t")
    private BigDecimal priceByOne;

    @DataField(pos = 4, delimiter = "\t")
    private BigDecimal count;

    @DataField(pos = 5, length = 2)
    private int foreignId;

    public int getLp() {
        return lp;
    }

    public void setLp(int lp) {
        this.lp = lp;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public BigDecimal getPriceByOne() {
        return priceByOne;
    }

    public void setPriceByOne(BigDecimal priceByOne) {
        this.priceByOne = priceByOne;
    }

    public BigDecimal getCount() {
        return count;
    }

    public void setCount(BigDecimal count) {
        this.count = count;
    }

    public int getForeignId() {
        return foreignId;
    }

    public void setForeignId(int foreignId) {
        this.foreignId = foreignId;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        str.append("...lp:").append(lp).append("\n");
        str.append("...id:").append(id).append("\n");
        str.append("...priceByOne:").append(priceByOne).append("\n");
        str.append("...count:").append(count).append("\n");
        str.append("...foreignId:").append(foreignId).append("\n");
        return str.toString();
    }

XmlOrder:

import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class XmlOrder extends OrderHeader {

    public XmlOrder() {
    }

    private List<Order> line;

    public XmlOrder(OrderHeader header, List<Order> lines) {
        this.setDate1(header.getDate1());
        this.setDate2(header.getDate2());
        this.setId(header.getId());
        this.setName(header.getName());
        this.setNumerOfFile(header.getNumerOfFile());
        this.setLines(lines);
    }

    public List<Order> getLines() {
        return line;
    }

    public void setLines(List<Order> lines) {
        this.line = lines;
    }

}

路线:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.converter.jaxb.JaxbDataFormat;
import org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat;

import com.stefan.test.fixedlengthtest.model.Order;
import com.stefan.test.fixedlengthtest.model.XmlOrder;
import com.stefan.test.fixedlengthtest.processors.ProcessOrder;

/**
 * A Camel Java8 DSL Router
 */
public class MyRouteBuilder extends RouteBuilder {

    public void configure() throws JAXBException {

        // Initialize JAXB
        JAXBContext jaxbContext = JAXBContext.newInstance(XmlOrder.class);
        JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(jaxbContext);

        //@formatter:off
        from("file:testdir").routeId("data-route")
            .unmarshal(new BindyFixedLengthDataFormat(Order.class))

            .to("log:test?showAll=true")

            .log("Loop through data")

            .process(new ProcessOrder())

            .marshal(jaxbDataFormat)
            .log("Order: \n${body}")

            .log("DATA processed")
        ;
    }
}

订单处理器:

import java.util.List;
import java.util.Map;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.stefan.test.fixedlengthtest.model.OrderHeader;
import com.stefan.test.fixedlengthtest.model.XmlOrder;

public class ProcessOrder implements Processor {

    private static final Logger logger = LoggerFactory.getLogger(ProcessOrder.class);

    @Override
    public void process(Exchange exchange) throws Exception {
        Map<String, OrderHeader> headermap = exchange.getIn()
                .getHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER, Map.class);

        OrderHeader header = headermap.get(OrderHeader.class.getName());

        logger.info("Processing order: {}", header.getId());
        logger.info("...date1: {}", header.getDate1());
        logger.info("...date2: {}", header.getDate2());
        logger.info("...numberOfFile: {}", header.getNumerOfFile());

        XmlOrder xmlorder = new XmlOrder(header, exchange.getIn().getBody(List.class));
        exchange.getIn().setBody(xmlorder);
    }
}

此示例路由将输出如下内容:

[                          main] ProcessOrder                   INFO  Processing order: 31
[                          main] ProcessOrder                   INFO  ...date1: 2018-11-01T00:00:00.000+0200
[                          main] ProcessOrder                   INFO  ...date2: 2018-10-31T00:05:16.000+0200
[                          main] ProcessOrder                   INFO  ...numberOfFile: 3
[                          main] data-route                     INFO  Order: 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xmlOrder>
    <date1>2018-11-01T00:00:00+02:00</date1>
    <date2>2018-10-31T00:05:16+02:00</date2>
    <id>31</id>
    <name>name</name>
    <numerOfFile>3</numerOfFile>
    <lines>
        <count>13</count>
        <foreignId>14</foreignId>
        <id>10</id>
        <lp>1</lp>
        <priceByOne>1</priceByOne>
    </lines>
    <lines>
        <count>14</count>
        <foreignId>14</foreignId>
        <id>20</id>
        <lp>2</lp>
        <priceByOne>1</priceByOne>
    </lines>
    <lines>
        <count>15</count>
        <foreignId>14</foreignId>
        <id>30</id>
        <lp>3</lp>
        <priceByOne>1</priceByOne>
    </lines>
</xmlOrder>

[                          main] data-route                     INFO  DATA processed

您可以在 github

中查看完整的资源