6

更新-下部の編集を参照してください

IDRefs / keyrefsはJAXBアノテーションで可能であるように見えますが、refは最終的に要素テキストになります。

refを要素の属性にしたいと思います。

たとえば、次のオブジェクトモデルがあるとします。

@XmlType
public class Employee {
    @XmlID
    @XmlAttribute
    String name;
    @XmlAttribute
    int years;
    @XmlAttribute
    String foo;
}

@XmlType
public class Office {
    @XmlAttribute
    String name;
    @XmlElementWrapper
    @XmlElement(name = "employee")
    List<Employee> employees;
}

@XmlRootElement
public class Company {
    @XmlElementWrapper
    @XmlElement(name = "office")
    List<Office> offices;
    @XmlElementWrapper
    @XmlElement(name = "employee")
    List<Employee> employees;
}

外部化されたxml形式を次のように表示したいと思います。

<company>
    <offices>
        <office name="nyc">
            <employees>
                <!--*** id ref to employee name ***-->
                <employee ref="alice"/>
                <employee ref="bob"/>
            </employees>
        </office>
        <office name="sf">
            <employees>
                <employee ref="connie"/>
                <employee ref="daphne"/>
            </employees>
        </office>
    </offices>
    <employees>
        <!-- *** name is the id *** -->
        <employee name="alice" years="3" foo="bar"/>
        <employee name="bob" years="3" foo="bar"/>
        <employee name="connie" years="3" foo="bar"/>
        <employee name="daphne" years="3" foo="bar"/>
    </employees>
</company>

代わりに、私ができる最善のことはこれです(Javaコードで上記の注釈を使用して):

<company>
    <offices>
        <office name="nyc">
            <employees>
                <employee>alice</employee>
                <employee>bob</employee>
            </employees>
        </office>
        <office name="sf">
            <employees>
                <employee>connie</employee>
                <employee>daphne</employee>
            </employees>
        </office>
    </offices>
    <employees>
        <employee name="alice" years="3" foo="bar"/>
        <employee name="bob" years="3" foo="bar"/>
        <employee name="connie" years="3" foo="bar"/>
        <employee name="daphne" years="3" foo="bar"/>
    </employees>
</company>

idref値を要素の本文ではなくemployeeの属性にする方法はありますか?XMLスキーマを使用してこれを実行できることはわかっていますが、可能な限り注釈を使用したいと思います。

ありがとうございました。

以下のTorious によるソリューションはほとんど機能しますが、状況によっては完全には機能しません。

「offices」要素が(xmlファイルで)officeが参照する「employee」要素の前にある場合、アンマーシャリングは失敗します。従業員参照が見つからず、EmployeeRefラッパーにnullの従業員オブジェクトがあります。「従業員」が最初の場合、それは機能します。

これはそれほど問題にはなりませんが、マーシャル方式では「オフィス」が最優先されるため、マーシャリングされたばかりのものをアンマーシャリングしようとすると失敗します。

Toriousの回答の2つのコメントを編集すると、順序の問題が解決します。

4

2 に答える 2

4

解決策は、新しいタイプのインスタンスでXmlAdapterをラップするを使用することです。これは、XMLIDrefをマップする方法を指定します。EmployeeEmployeeRef

@XmlType
public class Office {

    @XmlAttribute
    String name;

    @XmlElementWrapper
    @XmlElement(name="employee")
    @XmlJavaTypeAdapter(EmployeeAdapter.class) // (un)wraps Employee
    List<Employee> employees;
}

@XmlType
public class EmployeeRef {

    @XmlIDREF
    @XmlAttribute(name="ref")
    Employee employee;

    public EmployeeRef() {
    }

    public EmployeeRef(Employee employee) {
        this.employee = employee;
    }
}

public class EmployeeAdapter extends XmlAdapter<EmployeeRef, Employee> {

    @Override
    public EmployeeRef marshal(Employee employee) throws Exception {
        return new EmployeeRef(employee);
    }

    @Override
    public Employee unmarshal(EmployeeRef ref) throws Exception {
        return ref.employee;
    }
}

幸運を。

于 2012-04-14T02:44:44.077 に答える
2

注: 私はEclipseLink JAXB(MOXy)のリーダーであり、JAXB(JSR-222)エキスパートグループのメンバーです。

以下は、アノテーションを活用してMOXyでこれを行う方法の例です@XmlPathバグのため、2012年5月17日以降のEclipseLink 2.4.0ナイトリーラベルを使用する必要があります。この修正は、EclipseLink 2.3.3(2012年5月18日以降)ストリームにも追加されています。次の場所から夜間ラベルをダウンロードできます。

オフィス

employeesプロパティでは、注釈を注釈と組み合わせて使用​​して、@XmlIDREF目的@XmlPathのマッピングを取得できます。 @XmlIDREFオブジェクトの代わりに外部キーを書き出すようにJAXB実装に指示します。

package forum10150263;

import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlType
public class Office {
    @XmlAttribute
    String name;

    @XmlPath("employees/employee/@ref")
    @XmlIDREF
    List<Employee> employees;
}

従業員

に対応するの@XmlIDREF@XmlIDです。 @XmlIDオブジェクトの主キーを指定するために使用されます。

package forum10150263;

import javax.xml.bind.annotation.*;

@XmlType
public class Employee {
    @XmlID
    @XmlAttribute
    String name;

    @XmlAttribute
    int years;

    @XmlAttribute
    String foo;
}

会社

メカニズムを介して参照される各オブジェクトは@XmlIDREF、包含関係によっても参照される必要があります。この例では、これはemployeesプロパティによって実現されます。

package forum10150263;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Company {
    @XmlElementWrapper
    @XmlElement(name = "office")
    List<Office> offices;

    @XmlElementWrapper
    @XmlElement(name = "employee")
    List<Employee> employees;
}

jaxb.properties

jaxb.propertiesJAXBプロバイダーとしてMOXyを指定するには、ドメインモデルと同じパッケージで名前が付けられたファイルを次のエントリで追加する必要があります( JAXBプロバイダーとしてのEclipseLink MOXyの指定を参照) 。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

デモ

XMLのアンマーシャリング/マーシャリングには、標準のJAXBAPIが使用されます。

package forum10150263;

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

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum10150263/input.xml");
        Company company = (Company) unmarshaller.unmarshal(xml);

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

}

input.xml / Output

<?xml version="1.0" encoding="UTF-8"?>
<company>
   <offices>
      <office name="nyc">
         <employees>
            <employee ref="alice"/>
            <employee ref="bob"/>
         </employees>
      </office>
      <office name="sf">
         <employees>
            <employee ref="connie"/>
            <employee ref="daphne"/>
         </employees>
      </office>
   </offices>
   <employees>
      <employee name="alice" years="3" foo="bar"/>
      <employee name="bob" years="3" foo="bar"/>
      <employee name="connie" years="3" foo="bar"/>
      <employee name="daphne" years="3" foo="bar"/>
   </employees>
</company>

詳細については

于 2012-05-17T09:42:14.023 に答える