JAXB Unmarshalling with dynamic elements [duplicate]

我们两清 提交于 2021-01-27 17:31:29

问题


I have an XML as bellow.

 <hotelRoomDetails>
  <NightRates>
   <Night1>67</Night1>
   <Night2>67.5</Night2> 
   ........
   ........
   <Night25>65</Night25> 
  </NightRates>
  .......
  </hotelRoomDetails>

The element Night1,Night2,Night3 are always dynamic, and this count may vary from 1 to 35 times. Parent tag <NightRates> is always consistent.

The element <Night1>, <Night2> .. are not having any other attribute. It gives information about the hotel rate per night.

I want to create a 'LinkedList'(to preserve order) which contains the rate information of individual night. How can I handle this situation without knowing the occurrence count of element? How to create java class for this xml?


回答1:


Unmarshal Only

If you are just doing unmarshalling then you can use a StreamReaderDelegate to strip off the numeric suffix.

Demo

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

public class Demo {

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

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

        };

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

}

HotelRoomDetails

Then you have a collection property that maps to the element called Night.

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

@XmlRootElement
public class HotelRoomDetails {

    private List<String> nightRates = new ArrayList<String>();

    @XmlElementWrapper(name = "NightRates")
    @XmlElement(name = "Night")
    public List<String> getNightRates() {
        return nightRates;
    }

}

Unmarshal & Marshal

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

If you need to support reading and writing to this format you could use MOXy's @XmlVariableNode extension.

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



回答2:


You can make NightRates field of type any. And work with its content through org.w3c.dom.Element:

@XmlAnyElement
protected Element NightRates;


来源:https://stackoverflow.com/questions/19834756/jaxb-unmarshalling-with-dynamic-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!