2016-07-21 1 views
0

В настоящее время я пытаюсь размонтировать некоторый XML в объект java с использованием JAXB, и я получаю странное исключение Null Pointer. Это всего лишь проблема, в то время как неармаллирование. Я могу отлично обучать эти классы. Вот соответствующие фрагменты кода (несущественные части обозначаются «...»):Исключение Null Pointer при немаршаллировании XML с аннотацией @XmlAnyElement

  1. JAXB Корневой элемент:

    ... 
    @XmlRootElement(name="assets") 
    public class Assets { 
        String product; 
        Images images = new Images(); 
    
        ... 
    
        Public Assets() {} 
    
        ... 
    
        public String getProduct() { return this.product; } 
    
        @XmlAttribute(name="product") 
        public void setProduct(String newProduct) { this.product = newProduct; } 
    
        public Images getImages() { return this.images; } 
    
        @XmlElement(name="images") 
        public void setImages(Images newImages) { this.images = newImages; } 
    
        ... 
    } 
    
  2. Изображения подэлемент корневого элемента:

    ... 
    @XmlRootElement(name="images") 
    @XmlSeeAlso(Image.class) 
    @XmlType(propOrder = {"mainAsset", "image"}) 
    public class Images { 
        List<Image> images; 
        Image mainAsset; 
    
        private static char counter = 'a'; 
        private static final String prefix = "product-image-"; 
    
        // Here's the part that causes the NPE 
        @XmlAnyElement(lax=true) 
        public List<JAXBElement<Image>> getImage() { 
         final List<JAXBElement<Image>> imageList = new ArrayList<JAXBElement<Image>>(); 
         for (final Image g : this.images) { 
          imageList.add(new JAXBElement(new QName(prefix + counter++), Image.class, g)); 
         } 
         counter = 'a'; 
         return imageList; 
        } 
    
        @XmlElement(name="renditions") 
        public void setImage(List<Image> newImages) { this.images = newImages; } 
    
        public Image getMainAsset() { return this.mainAsset; } 
    
        @XmlElement(name="main-asset-name") 
        public void setMainAsset(Image newMainAsset) { this.mainAsset = newMainAsset; } 
    } 
    
  3. логика демаршаллизации в XML:

    ... 
    public void modifyXML() { 
    try { 
        JAXBContext context = JAXBContext.newInstance(Assets.class, Images.class, Image.class); 
        Unmarshaller um = context.createUnmarshaller(); 
        File f = new File("/path/to/my.xml"); 
        Assets assets = (Assets) um.unmarshal(f); 
        ... 
    } catch (JAXBException e) { 
        e.printStackTrace(); 
    } 
    } 
    ... 
    
  4. Наконец, XML я пытаюсь распаковать (это может помочь узнать, что этот файл XML был фактически создан с помощью маршаллер JAXB, который работает без каких-либо проблем):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <assets product="TEST PRODUCT"> 
        <images> 
         <main-asset-name> 
          <path>stuff.jpg</path> 
          <title>theTitle</path> 
          <alt>theAlt</path> 
          <description>theDescription</description> 
         </main-asset-name> 
         <product-image-a> 
          <path>48x48.jpg</path> 
          <title>theTitle</path> 
          <alt>theAlt</path> 
          <description>theDescription</description> 
         </product-image-a> 
         <product-image-b> 
          <path>140x140.jpg</path> 
          <title>theTitle</path> 
          <alt>theAlt</path> 
          <description>theDescription</description> 
         </product-image-b> 
         <product-image-c> 
          <path>1280x1280.jpg</path> 
          <title>theTitle</path> 
          <alt>theAlt</path> 
          <description>theDescription</description> 
         </product-image-c> 
         <product-image-d> 
          <path>319x319.jpg</path> 
          <title>theTitle</path> 
          <alt>theAlt</path> 
          <description>theDescription</description> 
         </product-image-d> 
        </images> 
    </assets> 
    

Okay , так что это все соответствующий код (я думаю). Когда я запускаю свою программу, я получаю следующую ошибку сразу после вызова unmarshaller:

java.lang.NullPointerException 
    at com.my.companys.name.Images.getImage(Images.java:25) 

И номер строки ссылки является строка, где цикл начинается в моем файле Images.java класса.

У кого-нибудь есть идеи, почему this.images может быть пустым здесь? Любая помощь приветствуется. Спасибо заранее.

+0

Я верю, что проблема заключается в том, что в XML-элементе отсутствует элемент renditions и, следовательно, изображения равны нулю. – lsiva

+0

Это хорошее предложение. Однако, даже если я удалю имя «выдачи» из аннотации '@ XmlElement', я все равно получаю ту же ошибку. – Pr4isethesun

+0

Вам нужно сопоставить узел XML, чтобы объект был установлен. – lsiva

ответ

0

Вот решение, которое я использовал сейчас. Это немного взломать, но, черт возьми ... Это делает работу.

Во-первых, я получаю необработанный XML в виде строки, а не читать его как файл:

public void modifyXML() { 
    try { 
     JAXBContext context = JAXBContext.newInstance(Assets.class, Image.class); 
     Unmarshaller um = context.createUnmarshaller(); 
     // This xml should be formatted in a way that JAXB can work with 
     String rawXML = getRawXML("/path/to/my.xml"); 
     // Hand the modified xml to the unmarshaller 
     Assets umAssets = (Assets) um.unmarshal(new StreamSource(new StringReader(rawXML))); 
     // Do stuff with umAssets 
     ... 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

private String getRawXML(String path) throws IOException { 
    String xml = readFile(path, StandardCharsets.UTF_8); 
    // This should make it so JAXB can handle the xml properly 
    xml = xml.replaceAll("<main-asset-name>", "<image>"); 
    xml = xml.replaceAll("</main-asset-name>", "</image>"); 
    xml = xml.replaceAll("<product-image.*>", "<image>"); 
    return xml.replaceAll("</product-image.*>", "</image>"); 
} 

private String readFile(String path, Charset encoding) throws IOException { 
    // A simple file reader 
    byte[] encoded = Files.readAllBytes(Paths.get(path)); 
    return new String(encoded, encoding); 
} 

Это, кажется, сделать трюк, так что я буду использовать это сейчас. Конечно, я все еще готов к лучшим решениям, если у кого-то есть.

Смежные вопросы