2012-10-28 18 views
5

Tôi có một tài liệu XML nhỏ ở định dạng FIXML. Tôi unmarshalling chúng bằng cách sử dụng jaxb.Jaxb unmarshalls đối tượng fixml nhưng tất cả các trường là null

Vấn đề

Quá trình hoàn toàn không có lỗi nhưng các đối tượng được tạo ra là hoàn toàn null. Mọi trường đều trống. Các trường là danh sách (như số lượng) có số lượng đối tượng phù hợp trong đó. Nhưng các trường của các đối tượng đó cũng không có giá trị.

Cài đặt

Tôi đã tải schema FIXML từ here và tôi đã tạo ra các lớp học với XJC và các plugin maven. Tất cả chúng đều nằm trong gói org.fixprotocol.fixml_5_0_sp2. Tôi đã có xml mẫu trong một file

FIXML.XML

<?xml version="1.0" encoding="ISO-8859-1"?> 
<FIXML> 
<Batch> 
    <PosRpt> 
    <Pty ID="GS" R="22"/> 
    <Pty ID="01" R="5"/> 
    <Pty ID="6U8" R="28"> 
     <Sub ID="2" Typ="21"/> 
    </Pty> 
    <Pty ID="GS" R="22"/> 
    <Pty ID="6U2" R="2"/> 
    <Instrmt ID="GHPKRW" SecTyp="FWD" MMY="20121018" MatDt="2012-10-18" Mult="1" Exch="GS" PxQteCcy="KJS" FnlSettlCcy="GBP" Fctr="0.192233298" SettlMeth="G" ValMeth="FWDC2" UOM="Ccy" UOMCCy="USD"> 
     <Evnt EventTyp="121" Dt="2013-10-17"/> 
     <Evnt EventTyp="13" Dt="2013-10-17"/> 
    </Instrmt> 
    <Qty Long="0.000" Short="22000000.000" Typ="PNTN"/> 
    <Qty Long="0.000" Short="22000000.000" Typ="FIN"/> 
    <Qty Typ="DLV" Long="0.00" Short="0.00" Net="0.0"/> 
    <Amt Typ="FMTM" Amt="32.332" Ccy="USD"/> 
    <Amt Typ="CASH" Amt="1" Rsn="3" Ccy="USD"/> 
    <Amt Typ="IMTM" Amt="329.19" Ccy="USD"/> 
    <Amt Typ="DLV" Amt="0.00" Ccy="USD"/> 
    <Amt Typ="BANK" Amt="432.23" Ccy="USD"/> 
</PosRpt> 

Sau đó tôi gọi unmarshaller với xử lý sự kiện tùy chỉnh mà chỉ ném một ngoại lệ trên lỗi phân tích cú pháp. Việc phân tích cú pháp hoàn chỉnh để tôi biết không có lỗi nào được tạo ra. Tôi cũng đang xử lý không gian tên như đề xuất here

// sort out the file 
String xmlFile = "C:\\FIXML.XML.xml"; 
System.out.println("Loading XML File..." + xmlFile); 
InputStream input = new FileInputStream(xmlFile); 
InputSource is = new InputSource(input); 

// create jaxb context 
JAXBContext jc = JAXBContext.newInstance("org.fixprotocol.fixml_5_0_sp2"); 
Unmarshaller unmarshaller = jc.createUnmarshaller(); 

// add event handler so jacB will fail on an error 
CustomEventHandler validationEventHandler = new CustomEventHandler(); 
unmarshaller.setEventHandler(validationEventHandler); 

// set the namespace 
NamespaceFilter inFilter = new NamespaceFilter("http://www.fixprotocol.org/FIXML-5-0-SP2", true); 

inFilter.setParent(SAXParserFactory.newInstance().newSAXParser().getXMLReader()); 
SAXSource source = new SAXSource(inFilter, is); 

// GO! 
JAXBElement<FIXML> fixml = unmarshaller.unmarshal(source, FIXML.class); 

Đối tượng fixml được tạo ra. Trong ví dụ trên, mảng Amt sẽ có năm phần tử khớp với số lượng amts trong tệp. Nhưng tất cả các trường như ccy là null. Tôi đã đặt các điểm ngắt trong các lớp được tạo bởi xjc và không có bộ định tuyến nào được gọi.

Vì vậy, nó xuất hiện rằng jaxb là unmarshalling và tạo tất cả các đối tượng chính xác, nhưng nó không bao giờ gọi các setters ??

Tôi hoàn toàn bối rối về điều này. Tôi đã nhìn thấy một vài bài viết mà suggrest đảm bảo rằng các tập tin package.info được tạo ra bởi xjc là trong packags và tôi đã chắc chắn rằng nó ở đó. Không có cảnh báo nào trong IDE về mã được tạo.

Bất kỳ trợ giúp nào được đánh giá cao.

Cập nhật Tôi đã cố gắng đặt tệp lược đồ trên trình gỡ lỗi trước khi bắt đầu unmarshalling.

Schema schema = sf.newSchema(f); 
unmarshaller.setSchema(schema); 

Tôi không biết lược đồ nào nên sử dụng nên tôi đã làm nó trong một vòng lặp thử mỗi tệp lần lượt. Các upshot là không ai trong số họ làm cho nó hoạt động. Chúng gây ra lỗi Nội dung không hợp lệ được tìm thấy bắt đầu bằng phần tử 'PosRpt'.

Điều gì thật đáng ngạc nhiên. Tôi đang nghĩ rằng vấn đề là một cái gì đó để làm với không gian tên.

Cập nhật 2 Vẫn không có tiến bộ. Tôi đã thử JAXB 2.0 & 2.2. Bây giờ hãy xem plugin maven khác để gọi xjc.Nhưng tôi không nghĩ vậy.

Cập nhật 3 Vì thế bây giờ đã đọc fixml trong tôi marshalling nó trở lại thành một file riêng biệt.

// GO! 
JAXBElement<FIXML> fixml = unmarshaller.unmarshal(source, FIXML.class); 

//Write  
Marshaller marshaller = jc.createMarshaller(); 
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
marshaller.marshal(fixml, output); 

Kết quả là:

inputfile.xml

<FIXML> 
    <Batch> 
    <PosRpt RptID="5952323" ReqID="434242" SetSesID="EOD" MtchStat="2" PriSetPx="11.284328" SetPx="11.4432" SetPxTyp="1" SettlCcy="EUR" ReqTyp="1" MsgEvtSrc="REG" BizDt="2012-11-17" SettlDt="2018-11-20"> 
     <Pty ID="CC" R="22"/> 
      .... 

output.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2"> 
     <Batch> 
      <PosRpt> 
       <Pty/> 
       <Pty/> 
       <Pty/> 

Vì vậy, cấu trúc của tập tin là chính xác, nhưng nó trống như mong đợi. Có một không gian tên rõ ràng vì vậy tôi đã thử thêm không gian tên đó vào tệp đầu vào thử nghiệm nhưng điều đó không tạo ra bất kỳ sự khác biệt nào. Tiếp theo, tôi sẽ thử populating đối tượng fixml trước khi sửa đổi nó.

Cập nhật 4

Không tôi là tạo ra một lớp FIXML đơn giản và marhelling nó.

simple_fxixml_out.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2" cv="DDDD"> 
    <Batch ID="dfddd"> 
     <PositionReportMessageT Ccy="CCC"/> 
    </Batch> 
</FIXML> 

Khi tôi cố gắng và đọc rằng trở lại trong tôi nhận được:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2"> 
    <Batch/> 

Những điều tôi lưu ý hình thức này là:

  1. Các tạo không gian tên giống nhau
  2. Tôi đã tạo PositionReportMessageT thay vì thẻ PosRpt
  3. Ngay cả thuộc tính DDDD trên FIXML không tồn tại trong quá trình chuyển đổi.
+1

Hãy thử tạo đối tượng JAXB trước tiên với một số dữ liệu mẫu, sau đó ghép nó vào một tệp. Kiểm tra xem nó có làm tròn các chuyến đi trở lại đối tượng JAXB khi bạn đọc lại không. Hãy xem các không gian tên trên tệp được tạo ra. – artbristol

+0

Bây giờ, đó là một ý tưởng hay. Sẽ cung cấp cho nó một đi (cập nhật để làm theo). – DUFF

Trả lời

2

Tôi nghĩ rằng bạn cần phải làm

saxParserFactory.setNamespaceAware(true)

(Tôi không nghĩ rằng bạn cần namespaceFilter)

Lớp javax.xml.bind.JAXB chứa phương tiện mà là rất hữu ích khi cố gắng ra marshalling/unmarshalling, bằng cách này.

+0

Cảm ơn, bạn đã phát hiện ra. – DUFF

0

Tìm thấy nó dễ dàng hơn để sử dụng thư viện FIXML sau (bạn có thể sử dụng maven để tải nó) https://javalibs.com/artifact/com.github.xgp/fixml

Sau đó sử dụng JAXB có trách nhiệm ràng buộc và traverse (sau đây là proof-of-concept mã đơn giản của riêng tôi):

JAXBContext jaxbContext = JAXBContext.newInstance(FIXML.class); 
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 

    FIXML fixml = (FIXML) unmarshaller.unmarshal(new StringReader(fixmlOrder)); 

    ExecutionReportMessageT er = (ExecutionReportMessageT) fixml.getMessage().getValue(); 
    if(er.getTrdDt() != null){ 
     System.out.println(er.getTrdDt().toGregorianCalendar().getTime()); 
    } 
    System.out.println(ToStringBuilder.reflectionToString(er,ToStringStyle.MULTI_LINE_STYLE)); 
Các vấn đề liên quan