package dogs;
@XmlRootElement(name = "dog")
public class Dog extends JAXBElement<String>{
public static final QName NAME = new QName("dog");
/**
*
*/
private static final long serialVersionUID = 1L;
private String dogName;
private String sound;
public Dog(String name) {
super(NAME, String.class, name);
}
public Dog(String dogName, String sound) {
super(NAME, String.class, sound);
this.dogName = dogName;
}
@Override
public QName getName() {
final String name = getDogName();
if(name != null) {
return new QName(name);
}
return NAME;
}
public String getDogName() {
return dogName;
}
public void setDogName(String dogName) {
this.dogName = dogName;
}
public String getSound() {
return sound;
}
public void setSound(String sound) {
this.sound = sound;
}
@Override
public String toString() {
return "Dog [dogName=" + dogName + ", sound=" + sound + "]";
}
}
package dogs;
@XmlRootElement(name = "listOfDogs")
public class Dogs {
private List<Object> dogs;
@XmlMixed
@XmlAnyElement
@XmlElementWrapper(name = "dogs")
public List<Object> getDogs() {
return this.dogs;
}
public void setDogs(List<Object> dogs) {
this.dogs = dogs;
}
public static void main(String[] args) throws JAXBException, FileNotFoundException, XMLStreamException {
JAXBContext context = JAXBContext.newInstance(Dogs.class);
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("dogs2.xml"));
xsr = new MyStreamReaderDelegate(xsr);
Unmarshaller unmarshaller = context.createUnmarshaller();
Dogs dogs = (Dogs) unmarshaller.unmarshal(xsr);
System.out.println(dogs.getDogs());
}
private static class MyStreamReaderDelegate extends StreamReaderDelegate {
public MyStreamReaderDelegate(XMLStreamReader xsr) {
super(xsr);
}
@Override
public String getAttributeLocalName(int index) {
return super.getAttributeLocalName(index);
}
@Override
public String getLocalName() {
if(super.getLocalName().equals("dog")) {
try {
super.nextTag();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
return super.getLocalName();
}
}
@Override
public String toString() {
return "Dogs [dogs=" + dogs + "]";
}
}
dogs2.xml文件是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<listOfDogs>
<dogs>
<dog>
<name>Henry</name>
<sound>Bark</sound>
</dog>
</dogs>
</listOfDogs>
上述代码的结果是:
[[name: null], [sound: null]]
但它应该是:
[Dog [dogName=Henry, sound=Bark]]
如您所见,不会调用类Dog的toString()方法。我尝试从JAXBElement重写getValue()以返回类Dog中的声音但没有结果,因为它没有被调用。在解组时,没有任何来自Dog类的东西被调用。而不是List狗,我宁愿有List狗,所以我可以从某个索引获取所有狗并调用getDogName()和getSound(); 我已经阅读了很多关于这个主题的帖子,但我找不到帮助我的东西。
我在哪里做错了?有其他选择吗?
答案 0 :(得分:0)
这不是一个答案,而是一个我无法使其发挥作用的声明。无论如何,我会报告,因为我认为这可能是一个有价值的意见。
我的想法是每个狗名实施一个ObjectFactory
方法:
@XmlRegistry
public class ObjectFactory {
public Dogs createDogs() {
return new Dogs();
}
@XmlElementDecl(name = "dog")
public Dog createDog(DogType value) {
return new Dog(value);
}
@XmlElementDecl(name = "fido", substitutionHeadName = "dog", substitutionHeadNamespace = "")
public Dog createFido(DogType value) {
return new Dog("fido", value);
}
@XmlElementDecl(name = "barks", substitutionHeadName = "dog", substitutionHeadNamespace = "")
public Dog createBarks(DogType value) {
return new Dog("barks", value);
}
}
我实际上预计在解组时会调用这些createBarks
和createFido
方法。这将在DogType
实例中设置狗名称。说实话,我很惊讶这些方法没有被调用。
但是,在解组时不会调用这些方法,因此我无法获得真正的标记名称。
我的想法没有用。如果有人想要试验,请点击我的代码here和here。
在我的测试中,名字未设置:
@Test
public void unmarshallsDogs() throws JAXBException {
final JAXBContext context = JAXBContext
.newInstance(ObjectFactory.class);
final Dogs dogs = (Dogs) context.createUnmarshaller().unmarshal(
getClass().getResource("dogs.xml"));
Assert.assertEquals(3, dogs.getDogs().size());
// Does not work
// Assert.assertEquals("henry", dogs.getDogs().get(0).getValue()
// .getName());
Assert.assertEquals("bark", dogs.getDogs().get(0).getValue().getSound());
// Does not work
// Assert.assertEquals("fido", dogs.getDogs().get(1).getValue()
// .getName());
Assert.assertEquals("woof", dogs.getDogs().get(1).getValue().getSound());
// Does not work
// Assert.assertEquals("barks", dogs.getDogs().get(2).getValue()
// .getName());
Assert.assertEquals("miau", dogs.getDogs().get(2).getValue().getSound());
}
请参阅Blaise Doughan的this answer获取基于XmlAdapter
的解决方案。
答案 1 :(得分:0)
解决方案1 - 根据您的xml文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<listOfDogs>
<dogs>
<dog>
<name>Henry</name>
<sound>Bark</sound>
</dog>
</dogs>
</listOfDogs>
@XMLRootElement(name="listOfDogs")
class ListOfDogs {
private Dogs dogs;
//Getters and Setters
@Override
public String toString(){
return dogs + "";
}
}
@XMLRootElement(name="dogs")
class Dogs {
List<Dog> dogs;
@XMLElement(name="dog")
public List<Dog> getDogs() {
return dogs;
}
//Setters
@Override
public String toString() {
return dogs + "";
}
}
@XmlRootElement(name = "dog")
public class Dog {
private String dogName;
private String sound;
@XmlElement(name = "name")
public String getDogName() {
return dogName;
}
public void setDogName(String dogName) {
this.dogName = dogName;
}
public String getSound() {
return sound;
}
public void setSound(String sound) {
this.sound = sound;
}
@Override
public String toString() {
return "Dog[" + "dogName=" + dogName + ", sound=" + sound + ']';
}
}
解决方案2:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dogs>
<dog>
<name>Henry</name>
<sound>Bark</sound>
</dog>
</dogs>
使用此解决方案,ListOfDogs类不再是utile.you可以删除它。