如何使用java注释读取xsi:type

如何使用java注释读取xsi:type,java,xml,jaxb,xml-namespaces,Java,Xml,Jaxb,Xml Namespaces,我想将基于jaxb的xml文件读入我的面向对象结构 假设这是我的xml文件: 12 符合事实的 10 符合事实的 children是一种包装器元素,包含多个子元素。孩子可以是xsi:type指定的男孩或女孩。这两个类有一些共同的元素(如年龄)和一些不同的元素(如isdancing或issoccerplayer) 要读取文件,我有以下方法: publicstaticvoidmain(字符串[]args)抛出jaxbeexception { JAXBContext JAXBContext; ja

我想将基于jaxb的xml文件读入我的面向对象结构

假设这是我的xml文件:


12
符合事实的
10
符合事实的
children是一种包装器元素,包含多个子元素。孩子可以是xsi:type指定的男孩或女孩。这两个类有一些共同的元素(如年龄)和一些不同的元素(如isdancing或issoccerplayer)

要读取文件,我有以下方法:

publicstaticvoidmain(字符串[]args)抛出jaxbeexception
{
JAXBContext JAXBContext;
jaxbContext=jaxbContext.newInstance(Children.class);
解组器jaxbUnmarshaller=jaxbContext.createUnmarshaller();
File File=新文件(“C:/test.xml”);
如果(!file.exists())System.out.println(“文件不存在”);
Children Children=(Children)jaxbunmarshall.unmarshal(文件);
System.out.println(children.toString());
}
我的儿童课是这样的:

@XmlAttribute(name = "type", namespace = XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)
private String xsiType;
@XmlRootElement(name=“children”)
@XmlAccessorType(XmlAccessType.FIELD)
公营儿童{
@xmlement(name=“child”)
私人名单儿童名单;
public List getChildren(){return childrenList;}
public void setChildren(列出子项){this.childrenList=children;}
@凌驾
公共字符串toString(){
返回StringBuilder.toString(this);
}
}
我的孩子班是这样的:

@XmlAttribute(name = "type", namespace = XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)
private String xsiType;
@xmlacessortype(xmlacesstype.FIELD)
公营儿童{
@XmlAttribute(name=“xsi:type”)
私有XsiType XsiType;
私人互联网;
@XmlElement(name=“isdancing”)
私有布尔运算;
@xmlement(name=“issoccerplayer”)
私有布尔型isSoccerPlayer;
//所有字段的Getter和setter
@凌驾
公共字符串toString(){
返回StringBuilder.toString(this);
}
}
我的XsiType类如下所示:

@XmlAttribute(name = "type", namespace = XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)
private String xsiType;
@xmlacessortype(xmlacesstype.FIELD)
公共类XsiType{
@XmlAttribute(name=“xsi:type”)
私有字符串名称;
@XmlValue
私有字符串值;
公共字符串getName(){return name;}
public void setName(字符串名){this.name=name;}
公共字符串getValue(){返回值;
public void setValue(字符串值){this.value=value;}
}
在我的pom.xml中,我包含了以下依赖项:


javax.xml.bind
jaxb api
2.3.1
org.apache.commons
commons-lang3
3.9
我现在的问题是,输出是正常的,但是子类的元素xsiType总是空的,否则它将以IllegalAnnotationExceptions结束,这与XmlTest.model.Child.xsiType相关

因此,我认为设置任何类型的@Xml注释都有错误。有人能帮我找到错误吗

目标是迭代子对象列表,并在运行时(基于xsiType)确定这是女孩还是男孩


谢谢

您不需要
XsiType
类。 您只需使用
字符串

在您的
子类中
xsiType
属性应该如下所示

@XmlAttribute(name = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
private String xsiType;
注意:在
@xmldattribute
注释中

  • 使用
    name=“type”
    (不带前缀
    xsi:
  • 指定XML中给定的参数 通过
    xmlns:xsi=“…”

顺便说一下:
而不是键入字符串
“http://www.w3.org/2001/XMLSchema-instance“
你最好用常数 . 因此,改进后的代码如下所示:

@XmlAttribute(name = "type", namespace = XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)
private String xsiType;

xsi类型通常用于表示对具体类型的引用

创建一个扩展子类的
Boy
Girl
类(您可能需要使用
@XmlType
调整类型名称)。这样,所有带有
xsi:type=Girl
的元素都将绑定到类
Girl

@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({ Boy.class, Girl.class }) // Either use @XmlSeeAlso to register classes in the JaxbContext
                                       //  or add them to the context directly
public class Child {

    private int age;

    @XmlElement(name = "isdancing")
    private boolean isDancing;

    @XmlElement(name = "issoccerplayer")
    private boolean isSoccerPlayer;

    // Getter and setter for all fields

}

@XmlType(name = "boy") // can be omitted if default value matches with the default value
public class Boy extends Child {

}

@XmlType(name = "girl")
public class Girl extends Child {

}
完整的自包含示例:

package jaxb;

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

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;

public class Inheritance {

    public static void main(String[] args) throws JAXBException {
        JAXBContext jaxbContext;
        jaxbContext = JAXBContext.newInstance(Children.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        String x = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\r\n"
                + "    <children xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n"
                + "        <child xsi:type=\"girl\">\r\n" + "            <age>12</age>\r\n"
                + "            <isdancing>true</isdancing>\r\n" + "        </child>\r\n"
                + "        <child xsi:type=\"boy\">\r\n" + "            <age>10</age>\r\n"
                + "            <issoccerplayer>true</issoccerplayer>\r\n" + "        </child>\r\n" + "    </children>";

        Children children = (Children) jaxbUnmarshaller.unmarshal(new StringReader(x));
        System.out.println(children.getChildren().toString());
    }

    @XmlRootElement(name = "children")
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Children {

        @XmlElement(name = "child")
        private List<Child> childrenList;

        public List<Child> getChildren() {
            return childrenList;
        }

        public void setChildren(List<Child> children) {
            this.childrenList = children;
        }

    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlSeeAlso({ Boy.class, Girl.class })
    public static class Child {

        private int age;

        @XmlElement(name = "isdancing")
        private boolean isDancing;

        @XmlElement(name = "issoccerplayer")
        private boolean isSoccerPlayer;

        // Getter and setter for all fields

    }

    @XmlType(name = "boy")
    public static class Boy extends Child {

    }

    @XmlType(name = "girl")
    public static class Girl extends Child {

    }
}
封装jaxb;
导入java.io.File;
导入java.io.StringReader;
导入java.util.List;
导入javax.xml.bind.JAXBContext;
导入javax.xml.bind.JAXBException;
导入javax.xml.bind.Unmarshaller;
导入javax.xml.bind.annotation.XmlAccessType;
导入javax.xml.bind.annotation.XmlAccessorType;
导入javax.xml.bind.annotation.xmlement;
导入javax.xml.bind.annotation.XmlRootElement;
导入javax.xml.bind.annotation.xmlsee;
导入javax.xml.bind.annotation.XmlType;
公共类继承{
公共静态void main(字符串[]args)抛出JAXBEException{
JAXBContext JAXBContext;
jaxbContext=jaxbContext.newInstance(Children.class);
解组器jaxbUnmarshaller=jaxbContext.createUnmarshaller();
字符串x=“\r\n”
+“\r\n”
+“\r\n”+“12\r\n”
+“真\r\n”+“\r\n”
+“\r\n”+“10\r\n”
+“true\r\n”+“\r\n”+”;
Children-Children=(Children)jaxbunmarshal.unmarshal(newstringreader(x));
System.out.println(children.getChildren().toString());
}
@XmlRootElement(name=“children”)
@XmlAccessorType(XmlAccessType.FIELD)
公立静态班儿童{
@xmlement(name=“child”)
私人名单儿童名单;
公共列表getChildren(){
返回儿童名单;
}
公共子项(列出子项){
this.childrenList=儿童;
}
}
@XmlAccessorType(XmlAc)