2010-12-07 60 views
4

正如標題所述,我想忽略文檔中元素名稱的外框。如何忽略JaxB中元素名稱的外框

static class XY433 { 
    @XmlAttribute(name = "C200") 
    String c200; 
    @XmlAttribute(name = "C215") 
    String c215; 

    @XmlAttribute(name="F001") 
    String f001; 

    @XmlAttribute(name="f001") 
    String lcf001; // I want to avoid this duplication 
} 

我試圖用張貼布萊斯Doughan代碼:

private static class ToLowerCaseNamesStreamReaderDelegate extends StreamReaderDelegate { 

    public ToLowerCaseNamesStreamReaderDelegate(XMLStreamReader xsr) { 
     super(xsr); 
    } 

    @Override 
    public String getAttributeLocalName(int index) { 
     return super.getAttributeLocalName(index).toLowerCase(); 
    } 

    @Override 
    public String getLocalName() { 
     return super.getLocalName().toLowerCase(); 
    } 

} 


@XmlRootElement(name="doc") 
static class Doc { 
    @XmlElement(name="element") 
    List<Element> elements; 
} 

static class Element { 
    @XmlAttribute(name = "abc") 
    String abc; 
} 

public static void main(String[] args) throws Exception { 
    XMLInputFactory xif = XMLInputFactory.newInstance(); 
    XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("LowerCaseElementNamesFilterTest.xml")); 

    Unmarshaller u = JAXBContext.newInstance(Doc.class).createUnmarshaller(); 

    //Do unmarshalling 
    Doc doc = (Doc) u.unmarshal(new ToLowerCaseNamesStreamReaderDelegate(xsr)); 

    System.out.println(doc.elements.get(0).abc); 
    System.out.println(doc.elements.get(1).abc); 
    System.out.println(doc.elements.get(2).abc); 

} 

這實際上沒有工作。

null 
2 
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 2 
    at java.util.ArrayList.RangeCheck(ArrayList.java:546) 
    at java.util.ArrayList.get(ArrayList.java:321) 
    at com.hre.commons.tec.xml.LowerCaseElementNamesFilter.main(LowerCaseElementNamesFilter.java:58) 

對於這個XML:

<doc> 
    <Element ABC="1"></Element> 
    <element Abc="1"></element> 
    <element abc="2"></element> 
</doc> 
+0

看看http://download.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/XmlAccessType.html#NONE和這個queistion是非常類似http://stackoverflow.com/questions/659872/how-do-i-prevent-jaxb-from-binding-superclass-methods-of-xmlrootelement-when :) – 2010-12-07 10:13:18

+1

我的問題與這個超類問題有什麼關係?我怎樣才能使用AccessType?我的問題是關於f001和lcf001。我只想要一個字段綁定到「F001」和「f001」。 – tkr 2010-12-07 12:33:01

回答

8

您可以將所有的屬性,以小寫節點名稱,然後換一個XMLStreamReader在其上返回的所有屬性/元素名稱調用toLowerCase()映射。然後從該XMLStreamReader解組。

我最近添加的EclipseLink JAXB(莫西)針對此問題的增強要求,隨時提供額外的信息:

對象模型

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Customer { 

    private int id; 
    private String name; 
    private Address address; 

    @XmlAttribute 
    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 Address getAddress() { 
     return address; 
    } 

    public void setAddress(Address address) { 
     this.address = address; 
    } 

} 


public class Address { 

    private String street; 

    public String getStreet() { 
     return street; 
    } 

    public void setStreet(String street) { 
     this.street = street; 
    } 

} 

演示代碼

import java.io.FileInputStream; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamReader; 
import javax.xml.stream.util.StreamReaderDelegate; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Customer.class); 

     XMLInputFactory xif = XMLInputFactory.newInstance(); 
     XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("input.xml")); 
     xsr = new MyStreamReaderDelegate(xsr); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Customer customer = (Customer) unmarshaller.unmarshal(xsr); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(customer, System.out); 
    } 

    private static class MyStreamReaderDelegate extends StreamReaderDelegate { 

     public MyStreamReaderDelegate(XMLStreamReader xsr) { 
      super(xsr); 
     } 

     @Override 
     public String getAttributeLocalName(int index) { 
      return super.getAttributeLocalName(index).toLowerCase(); 
     } 

     @Override 
     public String getLocalName() { 
      return super.getLocalName().toLowerCase(); 
     } 

    } 

} 

將讀取這些XML文檔:

<CUSTOMER ID="1"> 
    <NAME>Jane Doe</NAME> 
    <ADDRESS> 
     <STREET>123 A Street</STREET> 
    </ADDRESS> 
</CUSTOMER> 

<CuSToMeR Id="1"> 
    <NaMe>Jane Doe</NAME> 
    <AdDrEsS> 
     <STREET>123 A Street</STREET> 
    </AdDRrEsS> 
</CuSToMeR> 

,寫下面的XML:

<customer id="1"> 
    <address> 
     <street>123 A Street</street> 
    </address> 
    <name>Jane Doe</name> 
</customer> 

下面是一個更詳細的例子鏈接:

UPDATE

你的代碼工作在我的環境(JDK 1.6.0_20同時與包括JAXB,和JAXB的EclipseLink(莫西)2.2,我還使用StAX的默認實現)。當我運行你的例子:

import java.io.FileInputStream; 
import java.util.List; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamReader; 
import javax.xml.stream.util.StreamReaderDelegate; 

public class Example { 

    private static class ToLowerCaseNamesStreamReaderDelegate extends StreamReaderDelegate { 

     public ToLowerCaseNamesStreamReaderDelegate(XMLStreamReader xsr) { 
      super(xsr); 
     } 

     @Override 
     public String getAttributeLocalName(int index) { 
      return super.getAttributeLocalName(index).toLowerCase(); 
     } 

     @Override 
     public String getLocalName() { 
      return super.getLocalName().toLowerCase(); 
     } 

    } 


    @XmlRootElement(name="doc") 
    static class Doc { 
     @XmlElement(name="element") 
     List<Element> elements; 
    } 

    static class Element { 
     @XmlAttribute(name = "abc") 
     String abc; 
    } 

    public static void main(String[] args) throws Exception { 
     XMLInputFactory xif = XMLInputFactory.newInstance(); 
     XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("LowerCaseElementNamesFilterTest.xml")); 

     Unmarshaller u = JAXBContext.newInstance(Doc.class).createUnmarshaller(); 

     //Do unmarshalling 
     Doc doc = (Doc) u.unmarshal(new ToLowerCaseNamesStreamReaderDelegate(xsr)); 

     System.out.println(doc.elements.get(0).abc); 
     System.out.println(doc.elements.get(1).abc); 
     System.out.println(doc.elements.get(2).abc); 

    } 
} 

我得到以下輸出:

1 
1 
2 

更新#2

爲了解決:

異常線程 「main」 javax.xml.bind.UnmarshalException - 帶有鏈接的 例外: [javax.xml.bind。UnmarshalException: 命名空間URI和本地名稱,以解組需要在 的com.sun被扣留]在 com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:425) 的 。 .xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362) 在 com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:332)

您是否嘗試過修改的委託?:

@Override 
public String getAttributeLocalName(int index) { 
    return super.getAttributeLocalName(index).toLowerCase().intern(); 
} 

@Override 
public String getLocalName() { 
    return super.getLocalName().toLowerCase().intern(); 
} 
1

遇到類似的問題。 我的解決方案是在模型實體上添加@XmlAdpater,該模型實體指的是您自己的XMLAdapter,這將在marshall/unmarshall上提供靈活的自定義。