解析AWS S3存储桶XML时JAXB XML不解析任何内容

问题描述

我目前正在尝试使用JAXB库解析来自AWS S3存储桶的XML输出。尽管ListBucketobject没有内容,但我没有收到任何错误。我曾尝试将XmlAccessorTypes添加到Java POJO模型中,但收效甚微。有什么建议吗?

XML

<?xml version="1.0" encoding="UTF-8"?>
<ListBucketResult
    xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <Name>public-test-bucket</Name>
    <Prefix></Prefix>
    <Marker></Marker>
    <MaxKeys>1000</MaxKeys>
    <IsTruncated>false</IsTruncated>
    <Contents>
        <Key>202008281741/</Key>
        <LastModified>2020-08-31T15:38:24.000Z</LastModified>
        <ETag>&quot;d41d8cd98f00b204e9800998ecf8427e&quot;</ETag>
        <Size>0</Size>
        <Owner>
            <ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID>
            <displayName>aws-sandBox</displayName>
        </Owner>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
    <Contents>
        <Key>202008281741/161_209_2_0_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000</Key>
        <LastModified>2020-08-31T15:38:49.000Z</LastModified>
        <ETag>&quot;0834c2470b1e5183c27f7c67b589ff64&quot;</ETag>
        <Size>48328</Size>
        <Owner>
            <ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID>
            <displayName>aws-sandBox</displayName>
        </Owner>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
    <Contents>
        <Key>202008281741/161_209_2_1_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000</Key>
        <LastModified>2020-08-31T15:39:22.000Z</LastModified>
        <ETag>&quot;fca85f403ba0743c8a8559096728e86b&quot;</ETag>
        <Size>49259</Size>
        <Owner>
            <ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID>
            <displayName>aws-sandBox</displayName>
        </Owner>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
    <Contents>
        <Key>202008281741/161_209_2_2_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000</Key>
        <LastModified>2020-08-31T15:39:22.000Z</LastModified>
        <ETag>&quot;d4d9b9a1fdca74bda124548b7c303595&quot;</ETag>
        <Size>51296</Size>
        <Owner>
            <ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID>
            <displayName>aws-sandBox</displayName>
        </Owner>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
    <Contents>
        <Key>202008281741/161_209_2_3_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000</Key>
        <LastModified>2020-08-31T15:39:22.000Z</LastModified>
        <ETag>&quot;17b32ca673db491695b529c88397d583&quot;</ETag>
        <Size>53479</Size>
        <Owner>
            <ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID>
            <displayName>aws-sandBox</displayName>
        </Owner>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
    <Contents>
        <Key>test/</Key>
        <LastModified>2020-08-31T15:37:08.000Z</LastModified>
        <ETag>&quot;d41d8cd98f00b204e9800998ecf8427e&quot;</ETag>
        <Size>0</Size>
        <Owner>
            <ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID>
            <displayName>aws-sandBox</displayName>
        </Owner>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
    <Contents>
        <Key>test/33.txt</Key>
        <LastModified>2020-08-31T15:37:26.000Z</LastModified>
        <ETag>&quot;182be0c5cdcd5072bb1864cdee4d3d6e&quot;</ETag>
        <Size>2</Size>
        <Owner>
            <ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID>
            <displayName>aws-sandBox</displayName>
        </Owner>
        <StorageClass>STANDARD</StorageClass>
    </Contents>
</ListBucketResult>


Driver.java

package parseXML;

import java.io.StringReader;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;



public class Driver {
    

    public static void main(String[] args) {
        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + 
                "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>public-test-bucket</Name><Prefix></Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>202008281741/</Key><LastModified>2020-08-31T15:38:24.000Z</LastModified><ETag>&quot;d41d8cd98f00b204e9800998ecf8427e&quot;</ETag><Size>0</Size><Owner><ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID><displayName>aws-sandBox</displayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>202008281741/161_209_2_0_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000</Key><LastModified>2020-08-31T15:38:49.000Z</LastModified><ETag>&quot;0834c2470b1e5183c27f7c67b589ff64&quot;</ETag><Size>48328</Size><Owner><ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID><displayName>aws-sandBox</displayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>202008281741/161_209_2_1_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000</Key><LastModified>2020-08-31T15:39:22.000Z</LastModified><ETag>&quot;fca85f403ba0743c8a8559096728e86b&quot;</ETag><Size>49259</Size><Owner><ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID><displayName>aws-sandBox</displayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>202008281741/161_209_2_2_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000</Key><LastModified>2020-08-31T15:39:22.000Z</LastModified><ETag>&quot;d4d9b9a1fdca74bda124548b7c303595&quot;</ETag><Size>51296</Size><Owner><ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID><displayName>aws-sandBox</displayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>202008281741/161_209_2_3_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000</Key><LastModified>2020-08-31T15:39:22.000Z</LastModified><ETag>&quot;17b32ca673db491695b529c88397d583&quot;</ETag><Size>53479</Size><Owner><ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID><displayName>aws-sandBox</displayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>test/</Key><LastModified>2020-08-31T15:37:08.000Z</LastModified><ETag>&quot;d41d8cd98f00b204e9800998ecf8427e&quot;</ETag><Size>0</Size><Owner><ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID><displayName>aws-sandBox</displayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>test/33.txt</Key><LastModified>2020-08-31T15:37:26.000Z</LastModified><ETag>&quot;182be0c5cdcd5072bb1864cdee4d3d6e&quot;</ETag><Size>2</Size><Owner><ID>1eca891ffebb61124e238208a9df374b04731545fa5a646e8942a877bed5a24e</ID><displayName>aws-sandBox</displayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>";

        //convert into xml
        JAXBContext jaxbContext;
        try {
            jaxbContext = JAXBContext.newInstance(ListBucketResult.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            ListBucketResult listBucketResult = (ListBucketResult) jaxbUnmarshaller.unmarshal(new StringReader(xml));
            
            List<Contents> contents = listBucketResult.getContents();
            contents.forEach((content) -> System.out.println(content.getKey())); 
        } catch (JAXBException e) {
            System.out.println(e.getMessage());
        }
    }
}

ListBucketResult.java


package parseXML;

import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAttribute;

@XmlRootElement(name = "ListBucketResult",namespace = "http://s3.amazonaws.com/doc/2006-03-01/")
public class ListBucketResult {

    private String Name;
    private String Prefix;
    private String Marker;
    private int MaxKeys;
    private boolean IsTruncated;
    private List<Contents> Contents;

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public String getPrefix() {
        return Prefix;
    }

    public void setPrefix(String prefix) {
        Prefix = prefix;
    }

    public String getMarker() {
        return Marker;
    }

    public void setMarker(String marker) {
        Marker = marker;
    }

    public int getMaxKeys() {
        return MaxKeys;
    }

    public void setMaxKeys(int maxKeys) {
        MaxKeys = maxKeys;
    }

    @XmlAttribute
    public boolean isIsTruncated() {
        return IsTruncated;
    }

    public void setIsTruncated(boolean isTruncated) {
        IsTruncated = isTruncated;
    }

    public List<Contents> getContents() {
        return Contents;
    }

    public void setContents(List<Contents> contents) {
        Contents = contents;
    }

}

Contents.java

package parseXML;

public class Contents {
    private String Key;
    private String LastModified;
    private String ETag;
    private String Size;
    private Owner Owner;
    private String StroageClass;
    
    public String getKey() {
        return Key;
    }
    public void setKey(String key) {
        Key = key;
    }
    public String getLastModified() {
        return LastModified;
    }
    public void setLastModified(String lastModified) {
        LastModified = lastModified;
    }
    public String getETag() {
        return ETag;
    }
    public void setETag(String eTag) {
        ETag = eTag;
    }
    public String getSize() {
        return Size;
    }
    public void setSize(String size) {
        Size = size;
    }
    public Owner getowner() {
        return Owner;
    }
    public void setowner(Owner owner) {
        this.Owner = owner;
    }
    public String getStroageClass() {
        return StroageClass;
    }
    public void setStroageClass(String stroageClass) {
        StroageClass = stroageClass;
    }
    
    

}

Owner.java

package parseXML;

public class Owner {
    private String ID;
    private String displayName;

    public String getID() {
        return ID;
    }
    public void setID(String iD) {
        ID = iD;
    }
    public String getdisplayName() {
        return displayName;
    }
    public void setdisplayName(String displayName) {
        displayName = displayName;
    }
    
    
}

解决方法

一些观察结果:

  1. 处理命名空间

  2. 字母,设置器和字段名称

处理命名空间

不是像这样在ListBucketResult类的根元素上声明名称空间:

@XmlRootElement(name = "ListBucketResult",namespace = "http://s3.amazonaws.com/doc/2006-03-01/")

改为使用此:

@XmlRootElement(name = "ListBucketResult")

对于命名空间,请在package-info.java文件中进行处理。它是在parseXML包中创建的,其创建方式与您的类相同,但是具有以下内容:

@XmlSchema(
        namespace = "http://s3.amazonaws.com/doc/2006-03-01/",elementFormDefault = XmlNsForm.QUALIFIED)
package parseXML;

import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.XmlNsForm;

这可确保XML文件中的所有元素都是合格的,而不仅仅是与ListBucketResult类中的字段相关的元素。

字母,设置器和字段名称

我认为您命名Java字段的方式给您的getter / setter带来了麻烦,因为它们不符合JavaBeans命名约定。

示例:在您的ListBucketResult中,您有以下内容:

private List<Contents> Contents;

public List<Contents> getContents() {
    return Contents;
}

public void setContents(List<Contents> contents) {
    Contents = contents;
}

JavaBeans(和更广泛的Java)命名约定是使用带有驼峰的字段名-因此,在这种情况下为contents。然后相应地匹配getter和setter名称-通过将字段的首字母大写:getContentssetContets

对于XML,这意味着您还需要注释类中的字段名称,以便JAXB知道名为contents的Java字段映射到名为Contents的XML元素。

我选择对字段本身进行注释-因此我在类中添加了@XmlAccessorType注释,然后在字段中添加了@XmlElement注释。

我最后得到了-暂时忽略所有其他字段:

import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;

@XmlRootElement(name = "ListBucketResult",namespace = "http://s3.amazonaws.com/doc/2006-03-01/")
@XmlAccessorType(XmlAccessType.FIELD)
public class ListBucketResult {

    @XmlElement(name="Name")
    private String name;

    @XmlElement(name="Contents")
    private List<Contents> contents;

    public List<Contents> getContents() {
        return contents;
    }

    public void setContents(List<Contents> contents) {
        this.contents = contents;
    }
}

然后,在Contents类中,我必须做类似的事情-例如(同样,忽略key以外的所有字段):

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

@XmlAccessorType(XmlAccessType.FIELD)
public class Contents {

    @XmlElement(name="Key")
    private String key;

    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
}

如果对类中的其余字段重复此过程,则将具有完全填充的Java对象。

结果

通过仅进行上述更改,我的驱动程序代码(与您的代码相同)现在可以打印出以下结果:

202008281741/
202008281741/161_209_2_0_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000
202008281741/161_209_2_1_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000
202008281741/161_209_2_2_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000
202008281741/161_209_2_3_255_1_97_InitializedAnalysis_219_0m(AMSL)_0.000000_-1_-1.000000_-1.000000
test/
test/33.txt

通过对所有其余字段名称进行相同的更改,您将能够处理完整的XML文件。