2013-07-20 139 views
2

的名單上有JAXB解組:對象

@XmlRootElement(namespace = "http://www.w3.org/2005/Atom", name = "content") 
@XmlType(name = "course") 
public class Course implements Resource 

... 

@XmlElementWrapper(name="subcourses") 
@XmlElement(name="course") 
List<Xlink> subcourses;   //!? 

和XLink的類,它內聯變量工作正常。

public class Xlink 
{ 
    private String href; 
    private String value; 

    @XmlAttribute(namespace = "http://www.w3.org/1999/xlink") 
    public String getHref() 
    { 
     return href; 
    } 

    public void setHref(String href) 
    { 
     this.href = href; 
    } 

    @XmlValue 
    public String getValue() 
    { 
     return value; 
    } 

    public void setValue(String value) 
    { 
     this.value = value; 
    } 
} 

用於

<atom:content atom:type="xml" xsi:type="course"> 
... 
    <subcourses> 
     <course xlink:href="course1">Some course</course> 
     <course xlink:href="course2">other course</course> 

而且subcourses的XML輸入拒絕被解組(沒有被拋出任何異常)。

注意:MOXy不幸是不是一種選擇。

編輯:新編組對象

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns3:content xmlns:ns2="http://www.w3.org/1999/xlink" xmlns:ns3="http://www.w3.org/2005/Atom"> 
    <code>SOME CODE</code> 
    <name>name</name> 
    <subcourses> 
     <course ns2:href="Some href">some value</course> 
     <course ns2:href="sdsdg">sdfhdfhdhdh</course> 
    </subcourses> 
</ns3:content> 

EDIT2:經過一些實驗用解組和編組測試對象我發現我需要在內容的標頭中定義的xmlns命名空間來匹配xlink:href=xmlns:xlink="http://www.w3.org/1999/xlink"的問題在於我從一個由resteasy解析出來的包裝類中獲取Course元素。因此,結果類不包含名稱空間信息。

我以某種方式需要強制JAXB瞭解xmlns:xlink="http://www.w3.org/1999/xlink"適用於課程元素,但在谷歌一小時後我不知所措。

EDIT3:我從

https://github.com/jirutka/atom-jaxb/blob/master/src/main/java/cz/jirutka/atom/jaxb/Entry.java

這是對服務器對應使用

讓我的對象。這又是我的解組代碼

https://github.com/jirutka/atom-jaxb/blob/master/src/main/java/cz/jirutka/atom/jaxb/Feed.java

相關部分的一部分是:

Feed f = r.readEntity(Feed.class); 
out.addAll(unmarshaller.Unmarshal(f.getEntries(), clazz)); 

其中rjavax.ws.rs.core.Response。而且這個代碼是'wtf',因爲這是我第一次使用這種技術,所以這是完全可能的。

+0

你是什麼意思'拒絕被取消編組'?只是提供一個空的列表? – bmargulies

+0

是的,每次0項。 – Meltea

+0

你能提供更多關於你解開XML片段的地方的細節嗎? –

回答

5

當你註釋字段(實例變量)時,一定要把@XmlAccessorType(XmlAccessType.FIELD)放在你的類上。

import java.util.List; 
import javax.xml.bind.annotation.*; 

@XmlRootElement(namespace = "http://www.w3.org/2005/Atom", name = "content") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Course implements Resource { 

    @XmlElementWrapper(name = "subcourses") 
    @XmlElement(name = "course") 
    List<Xlink> subcourses; 

} 

然後確保您的XML輸入正確命名空間限定。你輸入的文件看起來應該像下面這樣:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<atom:content xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:atom="http://www.w3.org/2005/Atom"> 
    <code>SOME CODE</code> 
    <name>name</name> 
    <subcourses> 
     <course xlink:href="Some href">some value</course> 
     <course xlink:href="sdsdg">sdfhdfhdhdh</course> 
    </subcourses> 
</atom:content> 

隨着我的更新Course類,你Xlink類和下面的演示代碼工作完美的我一個正確的名稱空間限定的XML文檔。

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

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

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum17766166/input.xml"); 
     Course course = (Course) unmarshaller.unmarshal(xml); 

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

} 

更新#1

EDIT2:經過一些實驗用解組和編組一個 測試對象我發現我需要 的標題中定義的xmlns命名空間內容匹配xlink:href =類似 xmlns:xlink =「http://www.w3.org/1999/xlink」問題是我 從包裝器c中獲取Course元素這是通過resteasy解析 。因此,所得到的類不包含 名稱空間信息。

解決問題的最佳場所就是提取您希望展現的片段。以下是您可以與StAX一起使用的策略。

input.xml中

下面是其中的名稱空間信息是要解組片段如上定義的示例XML文檔。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<foo xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:atom="http://www.w3.org/2005/Atom"> 
    <bar> 
     <atom:content> 
      <code>SOME CODE</code> 
      <name>name</name> 
      <subcourses> 
       <course xlink:href="Some href">some value</course> 
       <course xlink:href="sdsdg">sdfhdfhdhdh</course> 
      </subcourses> 
     </atom:content> 
    </bar> 
</foo> 

演示

下面我們將用一個StAX的XMLStreamReader導航與靶標片段。我們將讓我們的JAXB實現解組這個片段。這樣所有的名字空間信息都被保留下來。

import javax.xml.bind.*; 
import javax.xml.stream.*; 
import javax.xml.transform.stream.StreamSource; 

public class Demo { 

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

     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     StreamSource source = new StreamSource("src/forum17766166/input.xml"); 
     XMLStreamReader xsr = xif.createXMLStreamReader(source); 
     while(xsr.hasNext()) { 
      if(xsr.isStartElement() && "content".equals(xsr.getLocalName())) { 
       break; 
      } 
      xsr.next(); 
     } 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Course course = (Course) unmarshaller.unmarshal(xsr); 

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

} 

輸出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns3:content xmlns:ns2="http://www.w3.org/1999/xlink" xmlns:ns3="http://www.w3.org/2005/Atom"> 
    <subcourses> 
     <course ns2:href="Some href">some value</course> 
     <course ns2:href="sdsdg">sdfhdfhdhdh</course> 
    </subcourses> 
</ns3:content> 

更新#2

如果如在更新#1中所描述你不能產生更好的XML片段,下面是你如何修復你當前擁有的XML片段。

NamespaceFilter

你可以使用SAX XMLFilter來修復您的XML文檔。

import org.xml.sax.*; 
import org.xml.sax.helpers.*; 

public class NamespaceFilter extends XMLFilterImpl { 

    private static final String ATOM_URI = "http://www.w3.org/2005/Atom"; 
    private static final String XLINK_URI = "http://www.w3.org/1999/xlink"; 

    @Override 
    public void startElement(String uri, String localName, String qName, 
      Attributes atts) throws SAXException { 
     if("atom:content".equals(qName)) { 
      super.startElement(ATOM_URI, "content", qName, atts); 
     } else if("course".equals(qName)) { 
      AttributesImpl modifiedAtts = new AttributesImpl(); 
      modifiedAtts.addAttribute(XLINK_URI, "href", "xlink:href", null, atts.getValue(0)); 
      super.startElement(uri, localName, qName, modifiedAtts); 
     } else { 
      super.startElement(uri, localName, qName, atts); 
     } 
    } 

    @Override 
    public void endElement(String uri, String localName, String qName) 
      throws SAXException { 
     if("atom:content".equals(qName)) { 
      super.endElement(ATOM_URI, "content", qName); 
     } else { 
      super.endElement(uri, localName, qName); 
     } 
    } 

} 

演示

下面是如何利用的XmlFilter與JAXB:

import javax.xml.bind.*; 
import javax.xml.parsers.*; 
import org.xml.sax.*; 

public class Demo { 

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

     // Create the XMLFilter 
     XMLFilter filter = new NamespaceFilter(); 

     // Set the parent XMLReader on the XMLFilter 
     SAXParserFactory spf = SAXParserFactory.newInstance(); 
     SAXParser sp = spf.newSAXParser(); 
     XMLReader xr = sp.getXMLReader(); 
     filter.setParent(xr); 

     // Set UnmarshallerHandler as ContentHandler on XMLFilter 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     UnmarshallerHandler unmarshallerHandler = unmarshaller 
       .getUnmarshallerHandler(); 
     filter.setContentHandler(unmarshallerHandler); 

     // Parse the XML 
     InputSource xml = new InputSource("src/forum17766166/input.xml"); 
     filter.parse(xml); 
     Course course = (Course) unmarshallerHandler.getResult(); 

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

} 

更多信息


更新#3

下面是你的示例代碼,一切工作的簡化版本。也許你的代碼有一些不同,它會幫助你找到。

進入

import javax.xml.bind.annotation.*; 

@XmlRootElement(namespace="http://www.w3.org/2005/Atom") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Entry<T> { 

    @XmlElement(namespace = "http://www.w3.org/2005/Atom") 
    @XmlSchemaType(name = "atomInlineOtherContent") 
    private T content; 

    public T getContent() { 
     return content; 
    } 

} 

的input.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<atom:entry xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:atom="http://www.w3.org/2005/Atom"> 
    <atom:content> 
     <code>SOME CODE</code> 
     <name>name</name> 
     <subcourses> 
      <course xlink:href="Some href">some value</course> 
      <course xlink:href="sdsdg">sdfhdfhdhdh</course> 
     </subcourses> 
    </atom:content> 
</atom:entry> 

演示

import java.io.File; 
import javax.xml.bind.*; 
import org.w3c.dom.Node; 

public class Demo { 

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

     // Unmarshal Entry 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum17766166/input.xml"); 
     Entry entry = (Entry) unmarshaller.unmarshal(xml); 

     // Unmarshal Course 
     Node contentNode = (Node) entry.getContent(); 
     Course course = (Course) unmarshaller.unmarshal(contentNode); 

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

} 

輸出

<?xml version="1.0" encoding="UTF-8"?> 
<ns0:content xmlns:ns1="http://www.w3.org/1999/xlink" xmlns:ns0="http://www.w3.org/2005/Atom"> 
    <subcourses> 
     <course ns1:href="Some href">some value</course> 
     <course ns1:href="sdsdg">sdfhdfhdhdh</course> 
    </subcourses> 
</ns0:content> 
+0

試圖實現這個,有一個問題。我從Response獲得的是已解析的XML節點的Node對象。我不能強制調用JAXB提供者的readEntity()給我一個String對象。如果我嘗試將它投入課程,則會拋出ElementNSImpl無法投射到課程。我確信我正在做一些錯誤的事情,但不知道是什麼。 – Meltea

+0

@Meltea - 你可以解組'Node'對象。 –