Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 基于对象属性的JAXB元素名称_Java_Jaxb_Quickbooks - Fatal编程技术网

Java 基于对象属性的JAXB元素名称

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>

我必须为以下XML创建对象模型:

XML示例1:

<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>

有关更多信息,请参阅:


要解决根元素方面的问题,您需要利用@XmlRegistry和@xmlementdecl。这将为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,我用示例代码更新了问题,以创建事务和示例输出。我想做一些稍微不同的事情——我想根据可映射对象的一个属性来命名该对象的顶级元素名。你能看一下吗。我已经根据更新开始了这个问题的新答案:。我不想删除这个例子,因为我相信它对社区有价值。非常感谢!看起来它现在能做到了。我会查的