使用 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
中查看完整的资源
我有这样的 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
中查看完整的资源