2013-07-20 136 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'对象。 –