4

2 つの XML ファイルがあります

ツリー.xml

<tree>
    <xi:include href="fruit.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <xi:fallback>
            <fruit/>
        </xi:fallback>
    </xi:include>
</tree>

果物.xml

<fruit>
     ...
</fruit>

ファイルを非整列化するコードを継承し、単一の Java オブジェクトを返します。ここで、1 つの Java オブジェクトを 2 つのファイルにマーシャリングする必要があります。私は他の解決策があることを認識しています (つまり、オプションである 1 つではなく 2 つのオブジェクトを使用します) が、単一のオブジェクトをマーシャリングし、xi:include を維持 (または再導入) し、2 つにエクスポート (または詳細) xml ファイル。

これは可能ですか?もしそうなら、ヒント/アイデアはありますか?

ありがとう

アップデート:

私はこれを調査しています(質問する前に調査しました)。私はこのチュートリアルhttp://tutorial.waycoolsearch.com/java/jaxb2.phpを見つけましたが、これには私の答えがあるように見えましたが、残念ながら、ファイルをマーシャリングすると、2 つだったものが 1 つになります。

4

2 に答える 2

4

以下ではXmlAdapter、このユース ケースでマーシャリングとアンマーシャリングの両方をサポートするために を使用する方法を示します。

XmlAdapter (IncludeFruitAdapter)

このXmlAdapterユースケースには を使用できます。

import java.io.File;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class IncludeFruitAdapter extends XmlAdapter<IncludeFruitAdapter.Include, Fruit> {

    private JAXBContext jc;
    private String href = "fruit.xml";

    public IncludeFruitAdapter() {
        try {
            jc = JAXBContext.newInstance(Fruit.class);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }


    public static class Include {

        @XmlAttribute
        public String href;

        @XmlElement(namespace="http://www.w3.org/2001/XInclude")
        public Fallback fallback;

    }

    public static class Fallback {

        @XmlElementRef
        public Fruit value;

    }

    @Override
    public Include marshal(Fruit fruit) throws Exception {
        File xml = new File(href);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(fruit, xml);

        Include include = new Include();
        include.href = href;
        include.fallback = new Fallback();
        include.fallback.value = new Fruit();
        return include;
    }

    @Override
    public Fruit unmarshal(Include include) throws Exception {
        File xml = new File(include.href);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        try {
            return (Fruit) unmarshaller.unmarshal(xml);
        } catch(Exception e) {
            return include.fallback.value;
        }
    }

}

@XmlJavaTypeAdapterを参照するために使用されますXmlAdapter

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Tree {

    @XmlJavaTypeAdapter(IncludeFruitAdapter.class)
    @XmlElement(name="include", namespace="http://www.w3.org/2001/XInclude")
    private Fruit fruit;

}

フルーツ

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {

    private String name;

}

デモ

以下は、すべてが機能することを証明するために実行できるデモ コードです。

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Tree.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("input.xml");
        Tree tree = (Tree) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(tree, System.out);

    }

}
于 2013-01-13T12:42:42.437 に答える
0

私は答え、少なくとも回避策を見つけました。この方法でよいのではないかと思います。

オブジェクトのセクションをマーシャリング用のインクルードとして定義する何らかの方法が JAXB にあることを期待していましたが、何も見つかりませんでした。

注:以下で説明する追加のハックが1つあります。それがなくても実行できると思いますが、動作させることができませんでした。他の誰かがこれを行う必要がある場合、少なくとも彼らは知っているでしょう。

流れは以下の通りです。

  1. XI:Include を含む 1 つの XML ファイルは、Java オブジェクトに非整列化されます。このオブジェクトには、2 つのファイル (親とインクルード) の内容が含まれています。
  2. オブジェクトが更新されます。
  3. オブジェクトは単一の一時ファイルにマーシャリングされます (これがハックです)。
  4. 単一の一時ファイルが DOM ドキュメントに umarhalled されます。(私は DOM ドキュメントに直接マーシャリングしたかったのですが、例外なく常に空の DOM ドキュメントを取得しました)。
  5. 次に、まず XI:Include に入る必要があるノードを削除して DOM ドキュメントを操作し、次に新しい XI:include ファイルを挿入します。
  6. DOM ドキュメントを xml ファイルに変換します。私の場合、XI:include の内容は変更されませんが、そのノードを新しいドキュメントに入れて変換できると思います。

まもなくコードを更新します。

これを解決する他の方法はありますか?

ありがとう、トラヴィス

于 2013-01-12T18:53:25.157 に答える