问题描述
我目前正在尝试使用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>"d41d8cd98f00b204e9800998ecf8427e"</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>"0834c2470b1e5183c27f7c67b589ff64"</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>"fca85f403ba0743c8a8559096728e86b"</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>"d4d9b9a1fdca74bda124548b7c303595"</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>"17b32ca673db491695b529c88397d583"</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>"d41d8cd98f00b204e9800998ecf8427e"</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>"182be0c5cdcd5072bb1864cdee4d3d6e"</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>"d41d8cd98f00b204e9800998ecf8427e"</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>"0834c2470b1e5183c27f7c67b589ff64"</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>"fca85f403ba0743c8a8559096728e86b"</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>"d4d9b9a1fdca74bda124548b7c303595"</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>"17b32ca673db491695b529c88397d583"</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>"d41d8cd98f00b204e9800998ecf8427e"</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>"182be0c5cdcd5072bb1864cdee4d3d6e"</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;
}
}
解决方法
一些观察结果:
-
处理命名空间
-
字母,设置器和字段名称
处理命名空间
不是像这样在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名称-通过将字段的首字母大写:getContents
,setContets
。
对于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文件。