当前位置: 首页 > 知识库问答 >
问题:

使用@XmlAnyElement注释解组XML时出现空指针异常

籍兴文
2023-03-14

我目前正试图使用JAXB将一些XML解组到一个java对象中,我得到了一个奇怪的空指针异常。这只是解组时的一个问题。我可以很好地处理这些类。以下是相关的代码片段(不相关的部分用“…”表示):

>

  • 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; }
    
        ...
    }
    

    元素的Images子元素:

    ...
    @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; }
    }
    

    解组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();
    }
    }
    ...
    

    最后,我试图散集的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>
    

    好的,这就是所有相关的代码(我想)。当我运行我的程序时,在调用解组器后立即出现以下错误:

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

    引用的行号是for循环在我的图像中开始的行。java类文件。

    有人知道为什么会这样吗。图像在此可能为空?非常感谢您的帮助。提前谢谢。

  • 共有1个答案

    司马项明
    2023-03-14

    这是我一直在使用的解决方案。这是一个有点黑客,但地狱。。。它起作用了。

    首先,我将原始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);
    }
    

    这似乎很管用,所以我现在就用这个。当然,如果有人有更好的解决方案,我仍然愿意接受。

     类似资料:
    • > 单击 受保护得空onPrepareDialog(int id,Dialog Dialog) 受保护的对话框onCreateDialog(int id) 如果我对timepickerdialog代码做了什么错误,请告诉我。

    • 我使用JAXB解组XML文件Java对象。 这个XML包含一个列表。例如 Java类为items提供@xmlementwrapper 当我试图解组时,会出现空指针异常。

    • 问题内容: MyClass.java: 编译MyClass.java文件的SimpleCompileTest.java的清单。 SimpleCompileTest.java: 我正在执行SimpleCompileTest类并获取NullPointerException。ToolProvider.getSystemJavaCompiler()返回null。有人可以告诉我代码有什么问题吗 问题答案:

    • 以下是在sun.reflect.nativeMethodAccessorImpl.Invoke0(本机方法)在sun.reflect.nativeMethodAccessorImpl.Invoke(未知源)在sun.reflect.NativeMethodAccessorImpl.Invoke(未知源)在java.lang.Reflect.Method.Invoke(未知源)在com.codena

    • 我为基本上是Bèzier路径的创建了一些。为此,我转换了类型为和的路径元素,为此我还有转换器: 我有一个测试代码: 混搭路径时创建的文件如下所示,这是我基本上想要的: 但是,在解组XML时,我遇到了这个异常: PathConverter中的第52行指向该行(在for循环中的第一次调用): 我的猜测是,这个问题与方法上的和方法有关,这样读者仍然处于它期望的结束节点的状态。对于其他两个转换器,我也有测

    • 我试图用Powermock和Mockito编写一个JUnit测试用例。我正在从测试用例下面调用一个方法。此方法从method1调用,而该方法调用Method2。我已经添加了@runwith和@preparefortest注释。 //这是我的测试类: 错误跟踪: