问题
I am trying to consume a CSV file using apache camel and convert each row to XML and publish each xml to solace topic. XML format is complex and I am not sure how to create such a complex XML in Java. CSV contains employee payload fields. Other part of XML including header, auditRecords and ancillaryData are hardcoded/static data(timestamp can be current date).
How to convert CSV to XML in Java using JAXB?
<canonMessage xmlns="http://www.test.com/canon/v1">
<header>
<metadata>
<domain>
<name>party</name>
<schemaVersion>1.0</schemaVersion>
<subdomain>
<name>employee</name>
</subdomain>
</domain>
<identifier>
<id idScheme="HR/lanId">kabcde</id>
</identifier>
<source>HR</source>
<messageId>352247</messageId>
<version>v1234520171106</version>
</metadata>
</header>
<payload>
<employee xmlns="http://www.testcompany.com/party/employee/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.testcompany.com/party/employee/v1 employee-v1.xsd">
<employeeId>a</employeeId>
<lanId>a</lanId>
<name>
<lastName>a</lastName>
<firstName>a</firstName>
</name>
<businessTitle>String</businessTitle>
<status>String</status>
<legalEntity>String</legalEntity>
<groupName>String</groupName>
<divisionName>String</divisionName>
<departmentName>String</departmentName>
<costCentre>String</costCentre>
<officeLocation>String</officeLocation>
<region>String</region>
<citizenship>
<citizenshipCountry>String</citizenshipCountry>
<citizenshipCountry>String</citizenshipCountry>
</citizenship>
</employee>
</payload>
<auditRecords>
<sourceAuditRecord>
<system>PeopleSoftHR</system>
<user />
<timestamp>
<created>2016-09-29T09:41:54.436+08:00</created>
<updated>2016-09-29T09:41:54.436+08:00</updated>
<sent>2016-09-29T09:42:48.366+08:00</sent>
</timestamp>
</sourceAuditRecord>
<auditRecord>
<system>listener-settlement</system>
<timestamp>
<received>2016-09-29T11:44:56.306+10:00</received>
</timestamp>
</auditRecord>
</auditRecords>
<ancillaryData>
<dataClassification xmlns="http://www.test.com/data-classification/v1">
<compartments>
<compartment name="domain">employee</compartment>
<compartment name="confidentiality">confidential</compartment>
</compartments>
</dataClassification>
</ancillaryData>
<trailer>
<checksum type="sha-256">df29183132b0733e5afbe5a9ab44f74ee7b43fff4d48daa</checksum>
</trailer>
</canonMessage>
Employee Class:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@CsvRecord(separator = ",")
public class Employee {
@DataField(pos = 1)
@XmlElement
public String employeeId;
@DataField(pos = 2)
@XmlElement
public String lanId;
@DataField(pos = 3)
@XmlElement
public String status;
@DataField(pos = 4)
@XmlElement
public String costCentre;
@DataField(pos = 5)
@XmlElement
public String groupName;
@DataField(pos = 6)
@XmlElement
public String divisionName;
@DataField(pos = 7)
@XmlElement
public String departmentName;
@DataField(pos = 8)
@XmlElement
public String region;
@DataField(pos = 9)
@XmlElement
public String businessTitle;
@DataField(pos = 10)
@XmlElement
public String officeLocation;
@DataField(pos = 11)
@XmlElement
public String legalEntity;
@DataField(pos = 12)
@XmlElement
public String birthDate;
@DataField(pos = 13)
@XmlElement
public String firstName;
@DataField(pos = 14)
@XmlElement
public String lastName;
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public String getLanId() {
return lanId;
}
public void setLanId(String lanId) {
this.lanId = lanId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCostCentre() {
return costCentre;
}
public void setCostCentre(String costCentre) {
this.costCentre = costCentre;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getDivisionName() {
return divisionName;
}
public void setDivisionName(String divisionName) {
this.divisionName = divisionName;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String getBusinessTitle() {
return businessTitle;
}
public void setBusinessTitle(String businessTitle) {
this.businessTitle = businessTitle;
}
public String getOfficeLocation() {
return officeLocation;
}
public void setOfficeLocation(String officeLocation) {
this.officeLocation = officeLocation;
}
public String getLegalEntity() {
return legalEntity;
}
public void setLegalEntity(String legalEntity) {
this.legalEntity = legalEntity;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Header Class:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="metadata")
@XmlAccessorType(XmlAccessType.FIELD)
public class Header {
@XmlElementWrapper(name = "domain")
private List<Domain> domain;
private String id;
private String source;
private String messageId;
private String version;
public List<Domain> getDomain() {
return domain;
}
public void setDomain(List<Domain> domain) {
this.domain = domain;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getMessageId() {
return messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public Header() {
}
public Header(List<Domain> domain, String id, String source, String messageId, String version) {
this.domain = domain;
this.id = id;
this.source = source;
this.messageId = messageId;
this.version = version;
}
}
Domain Class:
@XmlRootElement(name="domain")
@XmlAccessorType(XmlAccessType.FIELD)
public class Domain {
private String name;
private String schemaVersion;
//@XmlElementWrapper(name = "subdomain")
private String subdomain;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSchemaVersion() {
return schemaVersion;
}
public void setSchemaVersion(String schemaVersion) {
this.schemaVersion = schemaVersion;
}
public String getSubdomain() {
return subdomain;
}
public void setSubdomain(String subdomain) {
this.subdomain = subdomain;
}
public Domain() {
}
public Domain(String name, String schemaVersion, String subdomain) {
this.name = name;
this.schemaVersion = schemaVersion;
this.subdomain = subdomain;
}
}
Service:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.springframework.stereotype.Service;
@Service
public class HrCanonicalService {
private final String BOOKSTORE_XML = "app/hrci-files/bookstore-jaxb.xml";
public void process(Employee employee) {
JAXBContext context;
try {
context = JAXBContext.newInstance(CanonMessage.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
// Write to System.out
m.marshal(employee, System.out);
// Write to File
m.marshal(employee, new File(BOOKSTORE_XML));
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
回答1:
I managed to create the XML based on the above XML schema. I skipped ancillaryData and auditRecord elements as it was not mandatory. Let me know if this is the correct way of forming the XML.
CanonMessage.java
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="canonMessage")
@XmlAccessorType(XmlAccessType.FIELD)
public class CanonMessage {
@XmlElementWrapper(name = "header")
@XmlElement(name = "metadata")
private List<Header> metadata;
@XmlElementWrapper(name = "payload")
@XmlElement(name = "employee")
private List<Employee> employee;
@XmlElementWrapper(name = "auditRecords")
@XmlElement(name = "sourceAuditRecord")
private List<SourceAuditRecord> sourceAuditRecord;
@XmlElementWrapper(name = "trailer")
@XmlElement(name = "checksum")
private List<Trailer> trailer;
public List<Header> getMetadata() {
return metadata;
}
public void setMetadata(List<Header> metadata) {
this.metadata = metadata;
}
public List<Employee> getEmployee() {
return employee;
}
public void setEmployee(List<Employee> employee) {
this.employee = employee;
}
public List<SourceAuditRecord> getSourceAuditRecord() {
return sourceAuditRecord;
}
public void setSourceAuditRecord(List<SourceAuditRecord> sourceAuditRecord) {
this.sourceAuditRecord = sourceAuditRecord;
}
public List<Trailer> getTrailer() {
return trailer;
}
public void setTrailer(List<Trailer> trailer) {
this.trailer = trailer;
}
}
Header.java
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="metadata")
@XmlAccessorType(XmlAccessType.FIELD)
public class Header {
private List<Domain> domain;
@XmlElementWrapper(name = "identifier")
@XmlElement(name = "id")
private List<Identifier> identifier;
private String source;
private String messageId;
public List<Domain> getDomain() {
return domain;
}
public void setDomain(List<Domain> domain) {
this.domain = domain;
}
public List<Identifier> getIdentifier() {
return identifier;
}
public void setIdentifier(List<Identifier> identifier) {
this.identifier = identifier;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getMessageId() {
return messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public Header() {
}
public Header(List<Domain> domain, List<Identifier> identifier, String source, String messageId) {
this.domain = domain;
this.identifier = identifier;
this.source = source;
this.messageId = messageId;
}
}
Identifier.java
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
@XmlRootElement(name = "id")
@XmlAccessorType(XmlAccessType.FIELD)
public class Identifier {
@XmlAttribute(name = "idScheme")
private String id;
@XmlValue
private String Value;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getValue() {
return Value;
}
public void setValue(String value) {
Value = value;
}
}
Domain.java
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="domain")
@XmlAccessorType(XmlAccessType.FIELD)
public class Domain {
@XmlElement
private String name;
@XmlElement
private String schemaVersion;
@XmlElementWrapper(name = "subdomain")
@XmlElement(name = "name")
private List<String> subdomain;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSchemaVersion() {
return schemaVersion;
}
public void setSchemaVersion(String schemaVersion) {
this.schemaVersion = schemaVersion;
}
public List<String> getSubdomain() {
return subdomain;
}
public void setSubdomain(List<String> subdomain) {
this.subdomain = subdomain;
}
public Domain() {
}
public Domain(String name, String schemaVersion, List<String> subdomain) {
this.name = name;
this.schemaVersion = schemaVersion;
this.subdomain = subdomain;
}
}
Employee.java
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
import org.apache.camel.dataformat.bindy.annotation.DataField;
@XmlRootElement(namespace = Constants.EMPLOYEE_NAMESPACE)
@XmlAccessorType(XmlAccessType.FIELD)
@CsvRecord(separator = ",")
public class Employee {
@DataField(pos = 1)
@XmlElement
private String employeeId;
@DataField(pos = 2)
@XmlElement
private String lanId;
@DataField(pos = 3)
@XmlElement
private String status;
@DataField(pos = 4)
@XmlElement
private String costCentre;
@DataField(pos = 5)
@XmlElement
private String groupName;
@DataField(pos = 6)
@XmlElement
private String divisionName;
@DataField(pos = 7)
@XmlElement
private String departmentName;
@DataField(pos = 8)
@XmlElement
private String region;
@DataField(pos = 9)
@XmlElement
private String businessTitle;
@DataField(pos = 10)
@XmlElement
private String officeLocation;
@DataField(pos = 11)
@XmlElement
private String legalEntity;
@DataField(pos = 12)
@XmlElement
private String birthDate;
@XmlElement
private Name name;
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public String getLanId() {
return lanId;
}
public void setLanId(String lanId) {
this.lanId = lanId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCostCentre() {
return costCentre;
}
public void setCostCentre(String costCentre) {
this.costCentre = costCentre;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getDivisionName() {
return divisionName;
}
public void setDivisionName(String divisionName) {
this.divisionName = divisionName;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String getBusinessTitle() {
return businessTitle;
}
public void setBusinessTitle(String businessTitle) {
this.businessTitle = businessTitle;
}
public String getOfficeLocation() {
return officeLocation;
}
public void setOfficeLocation(String officeLocation) {
this.officeLocation = officeLocation;
}
public String getLegalEntity() {
return legalEntity;
}
public void setLegalEntity(String legalEntity) {
this.legalEntity = legalEntity;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
}
SourceAuditRecord.java
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="sourceAuditRecord")
@XmlAccessorType(XmlAccessType.FIELD)
public class SourceAuditRecord {
@XmlElement
private String system;
@XmlElement
private List<Timestamp> timestamp;
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
public List<Timestamp> getTimestamp() {
return timestamp;
}
public void setTimestamp(List<Timestamp> timestamp) {
this.timestamp = timestamp;
}
}
Timestamp.java
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="timestamp")
@XmlAccessorType(XmlAccessType.FIELD)
public class Timestamp {
@XmlElement
private String created;
@XmlElement
private String updated;
@XmlElement
private String sent;
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public String getUpdated() {
return updated;
}
public void setUpdated(String updated) {
this.updated = updated;
}
public String getSent() {
return sent;
}
public void setSent(String sent) {
this.sent = sent;
}
}
Trailer.java
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
@XmlRootElement(name = "checksum")
@XmlAccessorType(XmlAccessType.FIELD)
public class Trailer {
@XmlAttribute(name = "type")
private String checksum;
@XmlValue
private String Value;
public String getChecksum() {
return checksum;
}
public void setChecksum(String checksum) {
this.checksum = checksum;
}
public String getValue() {
return Value;
}
public void setValue(String value) {
Value = value;
}
}
Constants.java
public class Constants {
public static final String SHA_256_HEX = "sha-256";
public static final String HRCANONICAL_XML = "app/hrci-files/SampleEmployee_V1_20201103.xml";
public static final String EMPLOYEE_NAMESPACE = "http://www.xxxx/party/employee/v1";
public static final String HEADER_DOMAIN_NAME = "party";
public static final String HEADER_SCHEMA_VERSION = "1.0";
public static final String HEADER_SUB_DOMAIN_NAME = "employee";
public static final String HEADER_DOMAIN_SOURCE = "HRSystem";
public static final String HEADER_DOMAIN_MESSAGEID = "HRSystem";
public static final String HEADER_IDENTIFIER = "HRSystem/lanId";
}
Service.java
public void process(Employee employee) {
logger.info("process employee data started");
CanonMessage message = new CanonMessage();
// Set Header Record start
String correlationId = java.util.UUID.randomUUID().toString();
logger.info("correlationId - "+correlationId);
List<String> subDomainNameList = new ArrayList<>();
subDomainNameList.add(Constants.HEADER_SUB_DOMAIN_NAME);
Domain domain = new Domain(Constants.HEADER_DOMAIN_NAME, Constants.HEADER_SCHEMA_VERSION, subDomainNameList);
List<Domain> domainList = new ArrayList<>();
domainList.add(domain);
Identifier identifier = new Identifier();
List<Identifier> identifierList = new ArrayList<>();
identifier.setId(Constants.HEADER_IDENTIFIER);
identifier.setValue(employee.getLanId());
identifierList.add(identifier);
Header header = new Header(domainList, identifierList, Constants.HEADER_DOMAIN_SOURCE, correlationId);
List<Header> headerList = new ArrayList<>();
headerList.add(header);
message.setMetadata(headerList);
// Set Header Record end
// Set Employee Payload Record start
List<Employee> employeeList = new ArrayList<>();
employeeList.add(employee);
message.setEmployee(employeeList);
// Set Employee Payload Record start
// Set Audit Record start
SourceAuditRecord sourceAuditRecord = new SourceAuditRecord();
sourceAuditRecord.setSystem(Constants.HEADER_DOMAIN_SOURCE);
Timestamp timestamp = new Timestamp();
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime myDateObj = LocalDateTime.now();
String currentDateString = myDateObj.format(myFormatObj);
logger.info("currentDateString - "+currentDateString);
timestamp.setCreated(currentDateString);
timestamp.setSent(currentDateString);
List<Timestamp> timestampList = new ArrayList<>();
timestampList.add(timestamp);
sourceAuditRecord.setTimestamp(timestampList);
List<SourceAuditRecord> sourceAuditRecordList = new ArrayList<>();
sourceAuditRecordList.add(sourceAuditRecord);
message.setSourceAuditRecord(sourceAuditRecordList);
// Set Audit Record end
// Set Trailer Record start
String sha256hex = DigestUtils.sha256Hex(Constants.SHA_256_HEX);
logger.info("sha256hex - "+sha256hex);
List<Trailer> trailerList = new ArrayList<>();
Trailer trailer = new Trailer();
trailer.setChecksum(Constants.SHA_256_HEX);
trailer.setValue(sha256hex);
trailerList.add(trailer);
message.setTrailer(trailerList);
JAXBContext context;
try {
context = JAXBContext.newInstance(CanonMessage.class);
Marshaller jaxbMarshaller = context.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
// Write to System.out
jaxbMarshaller.marshal(message, System.out);
StringBuffer sb = new StringBuffer();
StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(message, sw);
String xmlString = sw.toString();
System.out.println("xmlString - "+xmlString);
SolaceTopicPublisher publisher = new SolaceTopicPublisher();
publisher.publishMessage(xmlString);
logger.info("Employee data processed");
} catch (JAXBException e) {
logger.error("Error occurred while creating XML data : "+e.getMessage());
e.printStackTrace();
}
}
来源:https://stackoverflow.com/questions/64637393/how-to-convert-csv-to-xml-in-java-using-jaxb