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

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


可以说这是我的 xml 文件:


    <?xml version="1.0" encoding="utf-8" standalone="yes"?>

    <children xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

        <child xsi:type="girl">

            <age>12</age>

            <isdancing>true</isdancing>

        </child>

        <child xsi:type="boy">

            <age>10</age>

            <issoccerplayer>true</issoccerplayer>

        </child>

    </children>

Children是某种包含多个子元素的包装元素。孩子可以是 xsi : type 指定的男孩或女孩。这两个类有一些共同的元素(如age)和一些不同(排除)的元素(如isdancing或issoccerplayer)


要读取文件,我有这个方法:


    public static void main( String[] args ) throws JAXBException

    {

        JAXBContext jaxbContext;

        jaxbContext = JAXBContext.newInstance(Children.class);             

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        File file = new File("C:/test.xml");

        if (!file.exists()) System.out.println("File does not exist");


        Children children = (Children) jaxbUnmarshaller.unmarshal(file);

        System.out.println(children.toString());

    }

我的孩子们的班级是这样的:


    @XmlRootElement(name="children")

    @XmlAccessorType(XmlAccessType.FIELD)

    public class Children {


        @XmlElement(name="child")

        private List<Child> childrenList;


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

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


    @Override

        public String toString() {

            return ReflectionToStringBuilder.toString(this);

        }

    }

我的孩子班看起来像这样:


    @XmlAccessorType(XmlAccessType.FIELD)

    public class Child {


    @XmlAttribute(name="xsi:type")

    private XsiType xsiType;


    private int age;


    @XmlElement(name = "isdancing")

    private boolean isDancing;


        }

    }

我现在的问题是,输出正常,但 Child-class 的元素 xsiType 始终为 null,否则最终会出现 IllegalAnnotationExceptions,这与 XmlTest.model.Child.xsiType 相关


所以我预计设置任何类型的 @Xml-Annotation 都会出现错误。有人可以帮我找出错误吗?


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


BIG阳
浏览 120回答 3
3回答

千巷猫影

你不需要你的XsiType课。您可以直接使用String。在你的Child类中xsiType,属性应该如下所示。@XmlAttribute(name = "type", namespace = "  private String xsiType;注意:在@XmlAttribute注释中使用name = "type"(不带前缀xsi:)指定namespaceXML 中给定的参数xmlns:xsi="..."顺便说一句: 您最好使用常量,而不是键入字符串。所以你的改进代码会是这样的:"http://www.w3.org/2001/XMLSchema-instance"XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI@XmlAttribute(name = "type", namespace = XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI) private String xsiType;

慕无忌1623718

xsi 类型通常用于表达对具体类型的引用。Jaxb 可以使用 xsi 类型,无需进一步的解决方法。创建一个Boy和 一个Girl扩展的类Children。(您可能需要使用 调整类型名称@XmlType)。这样,所有具有的元素都xsi:type=Girl将绑定到该类Girl@XmlAccessorType(XmlAccessType.FIELD)@XmlSeeAlso({ Boy.class, Girl.class }) // Either use @XmlSeeAlso to register classes in the JaxbContext&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//&nbsp; or add them to the context directlypublic class Child {&nbsp; &nbsp; private int age;&nbsp; &nbsp; @XmlElement(name = "isdancing")&nbsp; &nbsp; private boolean isDancing;&nbsp; &nbsp; @XmlElement(name = "issoccerplayer")&nbsp; &nbsp; private boolean isSoccerPlayer;&nbsp; &nbsp; // Getter and setter for all fields}@XmlType(name = "boy") // can be omitted if default value matches with the default valuepublic 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 {&nbsp; &nbsp; public static void main(String[] args) throws JAXBException {&nbsp; &nbsp; &nbsp; &nbsp; JAXBContext jaxbContext;&nbsp; &nbsp; &nbsp; &nbsp; jaxbContext = JAXBContext.newInstance(Children.class);&nbsp; &nbsp; &nbsp; &nbsp; Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();&nbsp; &nbsp; &nbsp; &nbsp; String x = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\r\n"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + "&nbsp; &nbsp; <children xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + "&nbsp; &nbsp; &nbsp; &nbsp; <child xsi:type=\"girl\">\r\n" + "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <age>12</age>\r\n"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <isdancing>true</isdancing>\r\n" + "&nbsp; &nbsp; &nbsp; &nbsp; </child>\r\n"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + "&nbsp; &nbsp; &nbsp; &nbsp; <child xsi:type=\"boy\">\r\n" + "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <age>10</age>\r\n"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <issoccerplayer>true</issoccerplayer>\r\n" + "&nbsp; &nbsp; &nbsp; &nbsp; </child>\r\n" + "&nbsp; &nbsp; </children>";&nbsp; &nbsp; &nbsp; &nbsp; Children children = (Children) jaxbUnmarshaller.unmarshal(new StringReader(x));&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(children.getChildren().toString());&nbsp; &nbsp; }&nbsp; &nbsp; @XmlRootElement(name = "children")&nbsp; &nbsp; @XmlAccessorType(XmlAccessType.FIELD)&nbsp; &nbsp; public static class Children {&nbsp; &nbsp; &nbsp; &nbsp; @XmlElement(name = "child")&nbsp; &nbsp; &nbsp; &nbsp; private List<Child> childrenList;&nbsp; &nbsp; &nbsp; &nbsp; public List<Child> getChildren() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return childrenList;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public void setChildren(List<Child> children) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.childrenList = children;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; @XmlAccessorType(XmlAccessType.FIELD)&nbsp; &nbsp; @XmlSeeAlso({ Boy.class, Girl.class })&nbsp; &nbsp; public static class Child {&nbsp; &nbsp; &nbsp; &nbsp; private int age;&nbsp; &nbsp; &nbsp; &nbsp; @XmlElement(name = "isdancing")&nbsp; &nbsp; &nbsp; &nbsp; private boolean isDancing;&nbsp; &nbsp; &nbsp; &nbsp; @XmlElement(name = "issoccerplayer")&nbsp; &nbsp; &nbsp; &nbsp; private boolean isSoccerPlayer;&nbsp; &nbsp; &nbsp; &nbsp; // Getter and setter for all fields&nbsp; &nbsp; }&nbsp; &nbsp; @XmlType(name = "boy")&nbsp; &nbsp; public static class Boy extends Child {&nbsp; &nbsp; }&nbsp; &nbsp; @XmlType(name = "girl")&nbsp; &nbsp; public static class Girl extends Child {&nbsp; &nbsp; }}

慕哥6287543

第二种方法的干净解决方案(基于单独的类文件):public class App{&nbsp; &nbsp; public static void main(String[] args) throws JAXBException&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; JAXBContext jaxbContext = JAXBContext.newInstance(Children.class);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();&nbsp; &nbsp; &nbsp; &nbsp; File file = new File("C:/test2.xml");&nbsp; &nbsp; &nbsp; &nbsp; Children children = (Children) jaxbUnmarshaller.unmarshal(file);&nbsp; &nbsp; &nbsp; &nbsp; for (Child c : children.getChildren()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c instanceof Boy) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println(((Boy)c).toString());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (c instanceof Girl){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println(((Girl)c).toString());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}Children.java@XmlRootElement(name="children")@XmlAccessorType(XmlAccessType.FIELD)public class Children {&nbsp; &nbsp; @XmlElement(name="child")&nbsp; &nbsp; private List<Child> childrenList;&nbsp; &nbsp; public List<Child> getChildren() { return childrenList; }&nbsp; &nbsp; public void setChildren(List<Child> children) {this.childrenList = children;}&nbsp; &nbsp; @Override&nbsp; &nbsp; public String toString() { return ReflectionToStringBuilder.toString(this); }}Boy.java@XmlType(name="boy")public class Boy extends Child {&nbsp; &nbsp; @XmlElement(name = "issoccerplayer")&nbsp; &nbsp; private boolean isSoccerPlayer;&nbsp; &nbsp; public boolean isSoccerPlayer() { return isSoccerPlayer; }&nbsp; &nbsp; public void setSoccerPlayer(boolean isSoccerPlayer) { this.isSoccerPlayer = isSoccerPlayer; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public String toString() { return ReflectionToStringBuilder.toString(this); }}Girl.java@XmlType(name="girl")public class Girl extends Child {&nbsp; &nbsp; @XmlElement(name = "isdancing")&nbsp; &nbsp; private boolean isDancing;&nbsp; &nbsp; public boolean isDancing() { return isDancing; }&nbsp; &nbsp; public void setDancing(boolean isDancing) { this.isDancing = isDancing; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public String toString() { return ReflectionToStringBuilder.toString(this); }}Child.java@XmlAccessorType(XmlAccessType.FIELD)@XmlSeeAlso({ Boy.class, Girl.class })&nbsp;public abstract class Child {&nbsp; &nbsp; private int age;&nbsp; &nbsp; public int getAge() { return age; }&nbsp; &nbsp; public void setAge(int age) { this.age = age; }}输出应该是:de.home.myproject.XmlTest.model.Girl@12edcd21[isDancing=true,age=12]de.home.myproject.XmlTest.model.Boy@27bc2616[isSoccerPlayer=true,age=10]
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java