7

JAXB は初めてで、XML ドキュメントを非整列化しようとしています。次のコマンドを使用してxjc、XSD ファイルから DataSet と ObjectFactory を構築しました。

<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="NewDataSet">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
        <xs:complexType>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="Table">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="AUTHOR" type="xs:string" minOccurs="0"/>
                            <xs:element name="TITLE" type="xs:string" minOccurs="0"/>
                            <xs:element name="ISBN" type="xs:string" minOccurs="0"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:choice>
        </xs:complexType>
    </xs:element>
</xs:schema>

生成されるNewDataSetクラスは次のとおりです。

package generated;

import java.util.ArrayList;
import java.util.List;
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.XmlType;


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "table"
})
@XmlRootElement(name = "NewDataSet")
public class NewDataSet {

    @XmlElement(name = "Table")
    protected List<NewDataSet.Table> table;

    public List<NewDataSet.Table> getTable() {
        if (table == null) {
            table = new ArrayList<NewDataSet.Table>();
        }
        return this.table;
    }


    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "author",
        "title",
        "isbn"
    })
    public static class Table {

        @XmlElement(name = "AUTHOR")
        protected String author;
        @XmlElement(name = "TITLE")
        protected String title;
        @XmlElement(name = "ISBN")
        protected String isbn;

        public String getAUTHOR() {
            return author;
        }

        public void setAUTHOR(String value) {
            this.author = value;
        }

        public String getTITLE() {
            return title;
        }
        public void setTITLE(String value) {
            this.title = value;
        }

        public String getISBN() {
            return isbn;
        }

        public void setISBN(String value) {
            this.isbn = value;
        }

    }

}

ObjectFactory

package generated;

import javax.xml.bind.annotation.XmlRegistry;


@XmlRegistry
public class ObjectFactory {

    public ObjectFactory() {
    }

    public NewDataSet createNewDataSet() {
        return new NewDataSet();
    }

    public NewDataSet.Table createNewDataSetTable() {
        return new NewDataSet.Table();
    }

}

非整列化しようとしている XML ファイルは次のとおりです。

<NewDataSet xmlns="">
    <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
        <Table diffgr:id="Table1" msdata:rowOrder="0">
            <AUTHOR>Kubo Tite</AUTHOR>
            <TITLE>Bleach</TITLE>
            <ISBN>1234456</ISBN>
        </Table>
        <Table diffgr:id="Table2" msdata:rowOrder="2">
            <AUTHOR>Masashi Kishimoto</AUTHOR>
            <TITLE>Naruto</TITLE>
            <ISBN>435345</ISBN>
        </Table>
        <Table diffgr:id="Table3" msdata:rowOrder="3">
            <AUTHOR>Eiichiro Oda</AUTHOR>
            <TITLE>One Piece</TITLE>
            <ISBN>56767</ISBN>
        </Table>
    </diffgr:diffgram>
</NewDataSet>

アンマーシャリングを行うコードは次のとおりです。

package consume;

import generated.NewDataSet;
import generated.NewDataSet.Table;

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

public class UnmarshallingCode {
    public static void main(String[] args) {
        try{
            File file=new File("data.xml");
            JAXBContext jb=JAXBContext.newInstance(NewDataSet.class);

            Unmarshaller unmarshaller=jb.createUnmarshaller();
            NewDataSet newDataSet=(NewDataSet)unmarshaller.unmarshal(file);
            for(Table t: newDataSet.getTable()){
                System.out.println(t.getTITLE());
            }
        }catch(JAXBException e){
            e.printStackTrace();
        }
    }
}

上記のコードはエラーを生成しませんが、結果を生成しません。呼び出しnewDataSet.getTable()は空のリストを返します。

ただし<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">、XML ファイルから とその関連属性を削除すると、上記のコードは正常に実行され、XML ドキュメント内のすべてのタイトルが生成されます。しかし、XML ドキュメントは非常に大きく、構造に大きな変更を加えることはおそらく許可されていないため、これは許容される解決策ではありません。上記の XML ファイルを非整列化するにはどうすればよいですか? ご意見をお聞かせください。

4

1 に答える 1

10

非整列化しようとしている XML ドキュメントは、XML スキーマに準拠していません。これが、JAXB (JSR-222)実装が期待どおりにデータを取り込まない理由であり、diffgr要素を削除するとデータが取り込まれる理由です。

余分な要素を削除する

XMLStreamReader余分な要素を削除してから非整列化するフィルターを作成できます。

XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/forum14234091/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);

xsr = xif.createFilteredReader(xsr, new StreamFilter() {
    @Override
    public boolean accept(XMLStreamReader xsr) {
        if(xsr.isStartElement() || xsr.isEndElement()) {
            return !"urn:schemas-microsoft-com:xml-diffgram-v1".equals(xsr.getNamespaceURI());
        }
        return true;
    }
});    

の作成JAXBContext

XML スキーマから JAXB モデルを生成する場合JAXBContext、ルート クラスではなく、生成されたクラスのパッケージ名に を作成する必要があります。これにより、生成されたすべてのアーティファクトが確実に処理されます。

JAXBContext jb=JAXBContext.newInstance("generated");

Unmarshaller unmarshaller=jb.createUnmarshaller();
NewDataSet newDataSet=(NewDataSet)unmarshaller.unmarshal(xsr);
for(Table t: newDataSet.getTable()){
    System.out.println(t.getTITLE());
}

パッケージ名の変更

デフォルトでは、生成されたクラスのパッケージ名はに基づいておりtargetNamespace、存在しgeneratedない場合はそうです。XJC 呼び出し中にパッケージ名を指定することもできます。

xjc -p com.example.foo schema.xsd
于 2013-01-09T11:40:01.127 に答える