2

同じ値を持つ @XmlID アノテーションが付けられたプロパティがいくつかある場合、型が異なっていても、JAXB はオブジェクトを正常に非整列化できませんでしたが、整列化は適切です。

バグですか?

または、その機能をサポートする方法は?

コード:

package xml;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public class MultiID {

    static public class LongXmlAdapter extends XmlAdapter<String, Long> {
        @Override
        public Long unmarshal(String s) {
            return Long.parseLong(s);
        }

        @Override
        public String marshal(Long number) {
            if (number == null) return "";

            return number.toString();
        }
    }


    static public class Element {
        private Long id;

        @XmlID
        @XmlAttribute(required=true)
        @XmlJavaTypeAdapter(LongXmlAdapter.class)
        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }
    }
    static public class Component {
        private Long id;

        @XmlID
        @XmlAttribute(required=true)
        @XmlJavaTypeAdapter(LongXmlAdapter.class)
        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        private Element elem;

        @XmlIDREF
        @XmlAttribute(required=true)
        public Element getElem() {
            return elem;
        }

        public void setElem(Element e) {
            this.elem = e;
        }
    }
    @XmlRootElement
    static public class Container {
        private List<Element> elemLst = new ArrayList<Element>();
        private List<Component> lst = new ArrayList<Component>();

        @XmlElementWrapper(name="elemList")
        @XmlElement(name="elem")
        public List<Element> getElemLst() {
            return (elemLst != null)?elemLst:(elemLst = new ArrayList<Element>());
        }

        public void setElemLst(List<Element> elemLst) {
            this.elemLst = elemLst;
        }

        @XmlElementWrapper(name="componentList")
        @XmlElement(name="component")
        public List<Component> getLst() {
            return (lst != null)?lst:(lst = new ArrayList<Component>());
        }

        public void setLst(List<Component> lst) {
            this.lst = lst;
        }
    }

    static public class XmlSerialization {
        public static Object read(String filepath, Class... classesToBeBound) throws FileNotFoundException {
            Object entity = null;
            try {
                File file = new File(filepath);
                if(!file.exists()) throw new FileNotFoundException(filepath);
                JAXBContext context = JAXBContext.newInstance(classesToBeBound);
                Unmarshaller um = context.createUnmarshaller();

                entity = um.unmarshal(file);
            } catch (JAXBException ex) {
                Logger.getLogger(XmlSerialization.class.getName()).log(Level.SEVERE, null, ex);
            }
            return entity;
        }

        public static void write(String filePath, Object entity, Class... classesToBeBound) {
            File file = new File(filePath);
            try {
                JAXBContext context = JAXBContext.newInstance(classesToBeBound);
                Marshaller m = context.createMarshaller();
                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                m.marshal(entity, file);
            } catch (JAXBException ex) {
                Logger.getLogger(XmlSerialization.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }
    public Container createContainer() {
        Container container = new Container();
        for(long i = 1 ; i < 5; ++i) {
            Element elem = new Element();
            elem.setId(i);
            container.getElemLst().add(elem);
            Component comp = new Component();
            comp.setId(i);
            comp.setElem(elem);
            container.getLst().add(comp);
        }
        return container;
    }
    public void write(String filePath, Container container) {
        XmlSerialization.write(filePath, container, Container.class, Component.class, Element.class);
    }
    public Container read(String filePath) {
        Container container = null;
        try {
            container = (Container)XmlSerialization.read(filePath, Container.class, Component.class, Element.class);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(MultiID.class.getName()).log(Level.SEVERE, null, ex);
        }
        return container;
    }

    public static void main(String[] args) {
        MultiID test = new MultiID();
        String filePath = "c:\\tmp.xml";
        Container c1 = test.createContainer();
        test.write(filePath, c1);
        Container c2 = test.read(filePath);
        filePath = "c:\\tmp2.xml";
        test.write(filePath, c2);
    }
}

出力:

[tmp.xml]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<container>
    <elemList>
        <elem id="1"/>
        <elem id="2"/>
        <elem id="3"/>
        <elem id="4"/>
    </elemList>
    <componentList>
        <component id="1" elem="1"/>
        <component id="2" elem="2"/>
        <component id="3" elem="3"/>
        <component id="4" elem="4"/>
    </componentList>
</container>

[tmp2.xml]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<container>
    <elemList>
        <elem id="1"/>
        <elem id="2"/>
        <elem id="3"/>
        <elem id="4"/>
    </elemList>
    <componentList>
        <component id="1"/>
        <component id="2"/>
        <component id="3"/>
        <component id="4"/>
    </componentList>
</container>

tmp2.xml のすべての「コンポーネント」には要素参照がありません。それが問題です。たとえば、100 から始まるコンポーネント ID を変更すると、期待どおりに動作します。

この問題を解決するにはどうすればよいですか? どうもありがとう。

4

2 に答える 2

1

出力は、使用しているJAXB (JSR-222)の実装のバグによるものです。Mac 用の JDK 1.7.0 とEclipseLink JAXB (MOXy)に含まれる JAXB impl を使用してサンプル コードを実行すると、tmp2.xml に対して期待される結果が得られます。

tmp2.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<container>
    <elemList>
        <elem id="1"/>
        <elem id="2"/>
        <elem id="3"/>
        <elem id="4"/>
    </elemList>
    <componentList>
        <component elem="1" id="1"/>
        <component elem="2" id="2"/>
        <component elem="3" id="3"/>
        <component elem="4" id="4"/>
    </componentList>
</container>
于 2012-09-30T10:27:06.217 に答える
1

XML の ID は、(a) XML ドキュメント全体で一意であり、(b) 有効な XML 名 (数字で始まっていない) でなければなりません。long を使用するのではなく、要素には 、 などのe1文字列を、コンポーネントには ... を使用することを検討してください。e2c1

于 2012-09-29T14:11:34.267 に答える