3

クラス Person があるとしましょう:

class Person{
  String firstName;
  String lastName;
  String email;
}

XML の形式は次のとおりです。

<person>
 <firstName value="asd" /> 
 <lastName value="bcd" />
 <email value="qwe" />
</person>

FirstNameAdapter、LastNameAdapter、EmailAdapter の各フィールドに対して独自の XmlAdapter 実装を使用して、このクラスをアンマーシャリング/マーシャリングできます。ご覧のとおり、各フィールドは同様の方法で表されています。フィールド名は xml 要素で、フィールド値は要素の属性です。フィールドの名前を転送できる「ユニバーサル」アダプターを作成して、そのフィールドの値を抽出することは可能ですか?

PS MOXy JAXB 実装については知っていますが、参照 JAXB 実装によって可能かどうか疑問に思っています。

ありがとう!

4

2 に答える 2

5

XmlAdapter次のように使用できます。

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

@XmlType
class Valued {
    @XmlAttribute(name="value")
    public String value;
}

class ValuedAdapter extends XmlAdapter<Valued, String> {
    public Valued marshal(String s) {
        Valued v = new Valued();
        v.value = s;
        return v;
    }
    public String unmarshal(Valued v) {
        return v.value;
    }
}

@XmlRootElement
class Person {

    @XmlJavaTypeAdapter(ValuedAdapter.class)
    @XmlElement
    String firstName;

    @XmlJavaTypeAdapter(ValuedAdapter.class)
    @XmlElement
    String lastName;

}

class SO12928971 {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        p.firstName = "John";
        p.lastName = "Doe";
        JAXBContext jc = JAXBContext.newInstance(Person.class);
        StringWriter sw = new StringWriter();
        jc.createMarshaller().marshal(p, sw);
        String xml = sw.toString();
        System.out.println(xml);
        StringReader sr = new StringReader(xml);
        p = (Person)jc.createUnmarshaller().unmarshal(sr);
        assert "John".equals(p.firstName);
        assert "Doe".equals(p.lastName);
    }
}

ここでの考え方は、XML スキーマと JAXB では、要素名コンテンツ タイプが明確に区別されているということです。ただし、多くのドキュメントでは、これら 2 つが明確に 1 対 1 で対応しています。したがって、上記のコードでは、 は要素名に関係なく、属性Valuedを持つものを表します。valueシリアル化するメンバーには@XmlElement、その注釈に名前が含まれていないという注釈が付けられています。そのため、メンバーの名前から派生した名前を持つ要素が生成されます。注釈により、@XmlJavaTypeAdapterシリアライザーはこれらのメンバーをその型が vere であるかのように扱いますValued。これが XML コンテンツ タイプになります。

上記のコードのスキーマは次のようになります。

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="person" type="person"/>

  <xs:complexType name="person">
    <xs:sequence>
      <xs:element name="firstName" type="valued" minOccurs="0"/>
      <xs:element name="lastName" type="valued" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="valued">
    <xs:sequence/>
    <xs:attribute name="value" type="xs:string"/>
  </xs:complexType>
</xs:schema>
于 2012-10-17T08:49:47.610 に答える
0

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

PS MOXy JAXBの実装については知っていますが、参照JAXBの実装によって可能かどうか疑問に思っています。

比較のために、EclipseLink JAXB(MOXy)の@XmlPath拡張機能を使用してこれを行う方法を追加しました。

package forum12928971;

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

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Person{

    @XmlPath("firstName/@value")
    String firstName;

    @XmlPath("lastName/@value")
    String lastName;

    @XmlPath("email/@value")
    String email;

}

jaxb.properties

MOXyをJAXBプロバイダーとして指定するにはjaxb.properties、ドメインモデルと同じパッケージで呼び出されるファイルを次のエントリで追加する必要があります。

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

デモ

package forum12928971;

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

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum12928971/input.xml");
        Person person = (Person) unmarshaller.unmarshal(xml);

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

}

input.xml / Output

<?xml version="1.0" encoding="UTF-8"?>
<person>
   <firstName value="asd"/>
   <lastName value="bcd"/>
   <email value="qwe"/>
</person>
于 2012-10-17T10:18:48.867 に答える