Java 基于对象属性的JAXB元素名称
我必须为以下XML创建对象模型: XML示例1:Java 基于对象属性的JAXB元素名称,java,jaxb,quickbooks,Java,Jaxb,Quickbooks,我必须为以下XML创建对象模型: XML示例1: <InvoiceAdd> <TxnDate>2009-01-21</TxnDate> <RefNumber>1</RefNumber> <InvoiceLineAdd> </InvoiceLineAdd> </InvoiceAdd> 目标是使用基于txnType的顶级元素名序列化t对象。例如: <InvoiceAdd>
<InvoiceAdd>
<TxnDate>2009-01-21</TxnDate>
<RefNumber>1</RefNumber>
<InvoiceLineAdd>
</InvoiceLineAdd>
</InvoiceAdd>
目标是使用基于txnType的顶级元素名序列化t对象。例如:
<InvoiceAdd>
<TxnDate>2009-01-21</TxnDate>
<RefNumber>1</RefNumber>
</InvoiceAdd>
2009-01-21
1.
如果是t.txnType=“SalesOrder”,则结果应为
<SalesOrderAdd>
<TxnDate>2009-01-21</TxnDate>
<RefNumber>1</RefNumber>
</SalesOrderAdd>
2009-01-21
1.
目前,我只看到一种解决方法,即使用子类InvoiceAdd和SalesOrderAdd,并使用@XmlElementRef注释根据类名来命名。但它需要根据事务类型实例化不同的类,还需要另外两个不同的类InvoiceLineAdd和SalesOrderLineAdd,这两个类看起来相当难看
请给我建议任何解决办法。我会考虑一些简单的事情。 < P>你可以使用XMLoad为这个。根据txnType属性的字符串值,您可以让XmlAdapter封送与InvoiceLineAdd或SalesOrderLineAdd相对应的对象实例 这就是它的样子: 交易添加
import javax.xml.bind.annotation.XmlSeeAlso;
@XmlSeeAlso({InvoiceAdd.class, SalesOrderAdd.class})
public class AbstractAdd {
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class InvoiceAdd extends AbstractAdd {
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class SalesOrderAdd extends AbstractAdd {
}
在txnType属性上,我们将使用@XmlJavaTypeAdapter和@xmlementref的组合:
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
public class TransactionAdd {
private String txnType;
@XmlJavaTypeAdapter(MyAdapter.class)
@XmlElementRef
public String getTxnType() {
return txnType;
}
public void setTxnType(String txnType) {
this.txnType = txnType;
}
}
调整后的对象将如下所示:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class MyAdapter extends XmlAdapter<AbstractAdd, String> {
@Override
public String unmarshal(AbstractAdd v) throws Exception {
if(v instanceof SalesOrderAdd) {
return "salesOrderAdd";
}
return "invoiceAdd";
}
@Override
public AbstractAdd marshal(String v) throws Exception {
if("salesOrderAdd".equals(v)) {
return new SalesOrderAdd();
}
return new InvoiceAdd();
}
}
摘要添加
import javax.xml.bind.annotation.XmlSeeAlso;
@XmlSeeAlso({InvoiceAdd.class, SalesOrderAdd.class})
public class AbstractAdd {
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class InvoiceAdd extends AbstractAdd {
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class SalesOrderAdd extends AbstractAdd {
}
发票添加
import javax.xml.bind.annotation.XmlSeeAlso;
@XmlSeeAlso({InvoiceAdd.class, SalesOrderAdd.class})
public class AbstractAdd {
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class InvoiceAdd extends AbstractAdd {
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class SalesOrderAdd extends AbstractAdd {
}
SalesOrderAdd
import javax.xml.bind.annotation.XmlSeeAlso;
@XmlSeeAlso({InvoiceAdd.class, SalesOrderAdd.class})
public class AbstractAdd {
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class InvoiceAdd extends AbstractAdd {
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class SalesOrderAdd extends AbstractAdd {
}
要在字符串和调整对象之间转换的XmlAdapter如下所示:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class MyAdapter extends XmlAdapter<AbstractAdd, String> {
@Override
public String unmarshal(AbstractAdd v) throws Exception {
if(v instanceof SalesOrderAdd) {
return "salesOrderAdd";
}
return "invoiceAdd";
}
@Override
public AbstractAdd marshal(String v) throws Exception {
if("salesOrderAdd".equals(v)) {
return new SalesOrderAdd();
}
return new InvoiceAdd();
}
}
要生成/使用以下XML:
<transactionAdd>
<salesOrderAdd/>
</transactionAdd>
有关更多信息,请参阅:
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
@XmlElementDecl(name="InvoiceAdd")
JAXBElement<TransactionAdd> createInvoiceAdd(TransactionAdd invoiceAdd) {
return new JAXBElement<TransactionAdd>(new QName("InvoiceAdd"), TransactionAdd.class, invoiceAdd);
}
@XmlElementDecl(name="SalesOrderAdd")
JAXBElement<TransactionAdd> createSalesOrderAdd(TransactionAdd salesOrderAdd) {
return new JAXBElement<TransactionAdd>(new QName("SalesOrderAdd"), TransactionAdd.class, salesOrderAdd);
}
}
import javax.xml.bind.JAXBElement;
导入javax.xml.bind.annotation.xmlementdecl;
导入javax.xml.bind.annotation.XmlRegistry;
导入javax.xml.namespace.QName;
@XmlRegistry
公共类对象工厂{
@xmlementdecl(name=“InvoiceAdd”)
JAXBElement createInvoiceAdd(事务添加invoiceAdd){
返回新的JAXBElement(新的QName(“InvoiceAdd”)、TransactionAdd.class、InvoiceAdd);
}
@xmlementdecl(name=“SalesOrderAdd”)
JAXBElement createSalesOrderAdd(事务添加salesOrderAdd){
返回新的JAXBElement(新的QName(“SalesOrderAdd”)、TransactionAdd.class、SalesOrderAdd);
}
}
您的TransactionAdd类将如下所示。需要注意的有趣的事情是,我们将使txnType属性@xmltransive
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
public class TransactionAdd {
private String txnDate;
private String refNumber;
private String txnType;
private List<LineAdd> lines;
@XmlElement(name="TxnDate")
public String getTxnDate() {
return txnDate;
}
public void setTxnDate(String txnDate) {
this.txnDate = txnDate;
}
@XmlElement(name="RefNumber")
public String getRefNumber() {
return refNumber;
}
public void setRefNumber(String refNumber) {
this.refNumber = refNumber;
}
@XmlTransient
public String getTxnType() {
return txnType;
}
public void setTxnType(String txnType) {
this.txnType = txnType;
}
public List<LineAdd> getLines() {
return lines;
}
public void setLines(List<LineAdd> lines) {
this.lines = lines;
}
}
import java.util.List;
导入javax.xml.bind.annotation.xmlement;
导入javax.xml.bind.annotation.XmlTransient;
公共类事务ADD{
私有字符串txnDate;
私有字符串引用号;
私有字符串txnType;
私有列表行;
@XmlElement(name=“TxnDate”)
公共字符串getTxnDate(){
返回TXN数据;
}
公共无效设置txnDate(字符串txnDate){
this.txnDate=txnDate;
}
@xmlement(name=“RefNumber”)
公共字符串getRefNumber(){
返回参考号;
}
公共void setRefNumber(字符串refNumber){
this.refNumber=refNumber;
}
@XmlTransient
公共字符串getTxnType(){
返回txnType;
}
公共无效设置txnType(字符串txnType){
this.txnType=txnType;
}
公共列表getLines(){
回流线;
}
公共无效设置行(列表行){
这条线=线;
}
}
然后我们需要在JAXB操作之外提供一些逻辑。对于解组,我们将使用根元素名称的本地部分来填充txnType属性。对于封送处理,我们将使用txnType属性的值来创建适当的JAXBElement
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(TransactionAdd.class, ObjectFactory.class);
File xml = new File("src/forum107/input1.xml");
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<TransactionAdd> je = (JAXBElement<TransactionAdd>) unmarshaller.unmarshal(xml);
TransactionAdd ta = je.getValue();
ta.setTxnType(je.getName().getLocalPart());
JAXBElement<TransactionAdd> jeOut;
if("InvoiceAdd".equals(ta.getTxnType())) {
jeOut = new ObjectFactory().createInvoiceAdd(ta);
} else {
jeOut = new ObjectFactory().createSalesOrderAdd(ta);
}
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(jeOut, System.out);
}
}
导入java.io.File;
导入javax.xml.bind.JAXBContext;
导入javax.xml.bind.JAXBElement;
导入javax.xml.bind.Marshaller;
导入javax.xml.bind.Unmarshaller;
公开课演示{
公共静态void main(字符串[]args)引发异常{
JAXBContext jc=JAXBContext.newInstance(TransactionAdd.class,ObjectFactory.class);
File xml=新文件(“src/forum107/input1.xml”);
Unmarshaller Unmarshaller=jc.createUnmarshaller();
JAXBElement je=(JAXBElement)unmarshaller.unmarshal(xml);
TransactionAdd ta=je.getValue();
ta.setTxnType(je.getName().getLocalPart());
杰克斯贝伦·杰奥特;
if(“InvoiceAdd”.equals(ta.getTxnType())){
jeOut=newObjectFactory().createInvoiceAdd(ta);
}否则{
jeOut=newObjectFactory().createSalesOrderAdd(ta);
}
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
元帅,元帅(全员,系统出局);
}
}
要做的事
接下来我将研究如何处理lines属性。太好了!谢谢@Blaise,我读了你的博客,但错过了这篇文章。现在我明白了,它可以帮助我。再给我一张小纸条。我可以在适配器中使用new-JAXBElement(new-QName(“SalesOrderLineAdd”)、LineAdd.class、lineAddObject之类的东西作为封送处理方法的输出吗?@Vladimir:我已经用一个代码示例更新了我的答案。诀窍是同时使用@XmlJavaTypeAdapter和@XmlElementRef。@Blaise,假设我想用对象b替换对象a。但我希望对象b是另一个顶级元素名的对象a,但内容相同。有没有可能使用某种特殊的包装来实现这一点。类似于:newjaxbwrapper(“b”,a)?@Blaise,我用示例代码更新了问题,以创建事务和示例输出。我想做一些稍微不同的事情——我想根据可映射对象的一个属性来命名该对象的顶级元素名。你能看一下吗。我已经根据更新开始了这个问题的新答案:。我不想删除这个例子,因为我相信它对社区有价值。非常感谢!看起来它现在能做到了。我会查的