困难的JAXB映射 [英] Difficult JAXB mapping

查看:91
本文介绍了困难的JAXB映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在更大的文档中映射以下XML结构,显然这不是XML的最大用途,但这是我必须使用的。

I am trying to map the following XML structure within a larger document, clearly this isn't the greatest use of XML ever but this is what I have to work with.

为简洁起见,简化示例:

Example simplified for clarity:

  <details>
    <pictures>
      <picture1>
        http://domain.com/path/picture1.jpg
      </picture1>
      <picture2>
        http://domain.com/path/picture2.jpg
      </picture2>
      <picture3>
        http://domain.com/path/picture3.jpg
      </picture3>
      <picture4>
        http://domain.com/path/picture4.jpg
      </picture4>
      <picture5>
        http://domain.com/path/picture5.jpg
      </picture5>
      <picture6>
        http://domain.com/path/picture6.jpg
      </picture6>
      <picture7>
        http://domain.com/path/picture7.jpg
      </picture7>
    </pictures>
  </details>

此文件有一个DTD,声明最多可有30个不同的图片元素,编号为1 -30名称< picutre [n] />

There is a DTD for this document which declares that there will be up to 30 different picture elements numbered 1-30 with the names <picutre[n]/>

我想做的是,而不是为每个元素创建30个不同的类,称为Picture1,Picture2,Picture3 ......等等。我只想使用一个Picture类并将其用于所有30个唯一元素名称。

What I would like to do is, rather than create 30 different classes for each of these elements called Picture1, Picture2, Picture3 ... and so on. I would just like to use a single Picture class and use it for all 30 unique element names.

以下是我到目前为止所尝试的内容。

Below is what I have tried so far.

@XmlRootElement
public class Details {

   ...

   @XmlElementWrapper
   @XmlElementRefs({
        @XmlElementRef( name="picture1", type=Picture.class ),
        @XmlElementRef( name="picture2", type=Picture.class ),
        @XmlElementRef( name="picture3", type=Picture.class ),
        @XmlElementRef( name="picture4", type=Picture.class ),
        @XmlElementRef( name="picture5", type=Picture.class ),
        @XmlElementRef( name="picture6", type=Picture.class ),
        @XmlElementRef( name="picture7", type=Picture.class ),
        @XmlElementRef( name="picture8", type=Picture.class ),
        @XmlElementRef( name="picture9", type=Picture.class ),
        @XmlElementRef( name="picture10", type=Picture.class ),
        @XmlElementRef( name="picture11", type=Picture.class ),
        @XmlElementRef( name="picture12", type=Picture.class ),
        @XmlElementRef( name="picture13", type=Picture.class ),
        @XmlElementRef( name="picture14", type=Picture.class ),
        @XmlElementRef( name="picture15", type=Picture.class ),
        @XmlElementRef( name="picture16", type=Picture.class ),
        @XmlElementRef( name="picture17", type=Picture.class ),
        @XmlElementRef( name="picture18", type=Picture.class ),
        @XmlElementRef( name="picture19", type=Picture.class ),
        @XmlElementRef( name="picture20", type=Picture.class ),
        @XmlElementRef( name="picture21", type=Picture.class ),
        @XmlElementRef( name="picture22", type=Picture.class ),
        @XmlElementRef( name="picture23", type=Picture.class ),
        @XmlElementRef( name="picture24", type=Picture.class ),
        @XmlElementRef( name="picture25", type=Picture.class ),
        @XmlElementRef( name="picture26", type=Picture.class ),
        @XmlElementRef( name="picture27", type=Picture.class ),
        @XmlElementRef( name="picture28", type=Picture.class ),
        @XmlElementRef( name="picture29", type=Picture.class ),
        @XmlElementRef( name="picture30", type=Picture.class )
    })
   public List<Picture> getPictures() {
      return this.pictures;
   }

   public void setPictures( List<Pictures> pictures ) {
      this.pictures = pictures;
   }

   ...

}

@XmlElementWrapper
public class Picture {
 ...
}

这会导致getPictures始终返回null。

This causes getPictures to return null always.

另外,我尝试将Picture类的注释更改为 @XmlElementWrapper(name =picture1),这导致我从中返回一个列表getPictures()但只包含< picture1 /> 元素,而不是其余元素。

Additionally I tried changing the annotation on the Picture class to be @XmlElementWrapper( name="picture1" ) which resulted in me getting a list returned from getPictures() but only ever containing the <picture1/> element and never the rest.

我知道我可以求助于获取JAXBElement对象的列表,但如果我可以避免它,我宁愿不这样做。我有什么想法可以映射这个吗?

I know I can resort to getting a list of JAXBElement objects instead but I would rather not if I can avoid it. Any ideas how I can map this?

推荐答案

有几种方法可以处理这个用例:

There are a couple ways you could handle this use case:

选项#1

您可以通过利用 @XmlElements执行以下操作

package forum10109418;

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

@XmlRootElement
public class Details {

   private List<Picture> pictures;

   @XmlElementWrapper
   @XmlElements({
       @XmlElement( name="picture1", type=Picture.class ),
       @XmlElement( name="picture2", type=Picture.class ),
       @XmlElement( name="picture3", type=Picture.class ),
       @XmlElement( name="picture4", type=Picture.class ),
       @XmlElement( name="picture5", type=Picture.class ),
       @XmlElement( name="picture6", type=Picture.class ),
       @XmlElement( name="picture7", type=Picture.class ),
       @XmlElement( name="picture8", type=Picture.class ),
       @XmlElement( name="picture9", type=Picture.class ),
       @XmlElement( name="picture10", type=Picture.class ),
       @XmlElement( name="picture11", type=Picture.class ),
       @XmlElement( name="picture12", type=Picture.class ),
       @XmlElement( name="picture13", type=Picture.class ),
       @XmlElement( name="picture14", type=Picture.class ),
       @XmlElement( name="picture15", type=Picture.class ),
       @XmlElement( name="picture16", type=Picture.class ),
       @XmlElement( name="picture17", type=Picture.class ),
       @XmlElement( name="picture18", type=Picture.class ),
       @XmlElement( name="picture19", type=Picture.class ),
       @XmlElement( name="picture20", type=Picture.class ),
       @XmlElement( name="picture21", type=Picture.class ),
       @XmlElement( name="picture22", type=Picture.class ),
       @XmlElement( name="picture23", type=Picture.class ),
       @XmlElement( name="picture24", type=Picture.class ),
       @XmlElement( name="picture25", type=Picture.class ),
       @XmlElement( name="picture26", type=Picture.class ),
       @XmlElement( name="picture27", type=Picture.class ),
       @XmlElement( name="picture28", type=Picture.class ),
       @XmlElement( name="picture29", type=Picture.class ),
       @XmlElement( name="picture30", type=Picture.class )
   })

   public List<Picture> getPictures() {
      return this.pictures;
   }

   public void setPictures( List<Picture> pictures ) {
      this.pictures = pictures;
   }

}

选项#2

您可以按如下方式映射详细信息类:

You could map your Details class as follows:

package forum10109418;

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

@XmlRootElement
public class Details {

   private List<Picture> pictures;

   @XmlElementWrapper
   @XmlElement(name="picture")
   public List<Picture> getPictures() {
      return this.pictures;
   }

   public void setPictures( List<Picture> pictures ) {
      this.pictures = pictures;
   }

}

然后使用 StreamReaderDelegate 切断数字后缀:

And then use a StreamReaderDelegate to chop off the numeric suffix:

package forum10109418;

import java.io.FileInputStream;
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.stream.util.StreamReaderDelegate;

public class Demo {

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

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("src/forum10109418/input.xml"));
        xsr = new StreamReaderDelegate(xsr) {
            @Override
            public String getLocalName() {
                String localName = super.getLocalName();
                if(localName.startsWith("picture") && !localName.equals("pictures")) {
                    return "picture";
                }
                return localName;
            }

        };
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Details details = (Details) unmarshaller.unmarshal(xsr);
        System.out.println(details.getPictures().size());
    }

}

选项#3

如果您使用的是 EclipseLink MOXy 作为您的 JAXB(JSR- 222) 提供商,然后您可以使用我们添加的 @XmlVariableNode 扩展程序:

If you are using EclipseLink MOXy as your JAXB (JSR-222) provider, then you could use the @XmlVariableNode extension that we added:

  • http://blog.bdoughan.com/2013/06/mapping-bad-xml-enumerated-collection.html

这篇关于困难的JAXB映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆