<?xml version="1.0" encoding="UTF-8"?><project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>Jaxb2Exam</groupId>
  <artifactId>Jaxb2Exam</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <description></description>
  <build>
    <plugins>
      <plugin>
        <groupId>org.jvnet.jaxb2.maven2</groupId>
        <artifactId>maven-jaxb2-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>generate</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <schemaDirectory>src/main/resources/schema</schemaDirectory>
          <generateDirectory>src/main/java/</generateDirectory>
          <generatePackage>com.snail.exam.jaxb.object</generatePackage>
          <!-- これを入れないと src/main/java/ 以下を全て削除されてしまう -->
          <removeOldOutput>false</removeOldOutput>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <inherited>true</inherited>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <repositories>
    <repository>
      <id>maven2-repository.dev.java.net</id>
      <name>Java.net Maven 2 Repository</name>
      <url>http://download.java.net/maven/2</url>
    </repository>
    <repository>
      <id>maven-repository.dev.java.net</id>
      <name>Java.net Maven 1 Repository (legacy)</name>
      <url>http://download.java.net/maven/1</url>
      <layout>legacy</layout>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <id>maven2-repository.dev.java.net</id>
      <name>Java.net Maven 2 Repository</name>
      <url>http://download.java.net/maven/2</url>
    </pluginRepository>
    <pluginRepository>
      <id>maven-repository.dev.java.net</id>
      <name>Java.net Maven 1 Repository (legacy)</name>
      <url>http://download.java.net/maven/1</url>
      <layout>legacy</layout>
    </pluginRepository>
  </pluginRepositories>
</project>
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<xsd:include schemaLocation="EmployeeInfo.xsd" />
	
    <!-- JAXBテスト用 -->
    <xsd:element name="Employee">
        <xsd:complexType>
            <xsd:sequence>
            	<xsd:element name="name" type="xsd:string"/>
            	<!--
            	あってもなくても良い項目、maxOccurs を設定すると List になるので
            	minOccurs のみ定義する
            	-->
            	<xsd:element name="sex" type="sex_t" minOccurs="0" maxOccurs="1"/>
            	<!--
            	1つから3つの繰り返し
            	-->
            	<xsd:element name="phone" type="phonecode_t" minOccurs="1" maxOccurs="3"/>
            	<!--
            	0個以上の繰り返し
            	-->
            	<xsd:element name="post" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
            	<!--
            	複合項目の繰り返し
            	-->
            	<xsd:element name="qualification" type="qualification_t" minOccurs="0" maxOccurs="unbounded"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>    
</xsd:schema>
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <!-- JAXBUtilテスト用 -->
    <!-- 型定義 -->
    <!--
      電話番号
      <phone type="office">01-2345-6789</phone> の様に、XML構造の末端で
      属性をもつ場合。(+ 型検証)
      
      xsd:string を継承して、正規表現チェック機能を持った phonecode_base型
      を作る。phonecode_base を継承して、属性をもった phonecode_t型を作る。
    -->
    <xsd:simpleType name="phonecode_base">
        <xsd:restriction base="xsd:string">
            <xsd:pattern value="[0-9]{2,3}-[0-9]{3,4}-[0-9]{3,4}"/>
        </xsd:restriction>
    </xsd:simpleType>    
    
    <xsd:complexType name="phonecode_t">
		<xsd:simpleContent>
			<xsd:extension base="phonecode_base">
				<xsd:attribute name="type" type="xsd:string" use="optional"/>
			</xsd:extension>
		</xsd:simpleContent>
    </xsd:complexType>
    
    <!--
      性別
      <sex type="m"/> の様に、属性のみがある場合  
    -->
    <xsd:complexType name="sex_t">
		<xsd:sequence>
		</xsd:sequence>
		<xsd:attribute name="type" type="xsd:string" use="optional"/>
	</xsd:complexType>
    
    <!--
      資格
      <qualification valid="true">
        <title>3級陰陽師</title>
        <date>1024-03-02</date>
        <copy>0123456789ABCDEF</copy>
      </qualification>
      の様に、子要素と属性をもつ場合
    -->
	<xsd:complexType name="qualification_t">
		<xsd:sequence>
			<xsd:element name="title" type="xsd:string"/>
			<xsd:element name="date" type="xsd:date"/>
			<xsd:element name="copy" type="xsd:hexBinary"/>
		</xsd:sequence>
		<xsd:attribute name="valid" type="xsd:boolean" use="optional"/>
	</xsd:complexType>
</xsd:schema>
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-520 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2008.11.06 at 12:39:37 午前 JST 
//
package com.snail.exam.jaxb.object;
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;
/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * <complexType>
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *         <element name="sex" type="{}sex_t" minOccurs="0"/>
 *         <element name="phone" type="{}phonecode_t" maxOccurs="3"/>
 *         <element name="post" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
 *         <element name="qualification" type="{}qualification_t" maxOccurs="unbounded" minOccurs="0"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "name",
    "sex",
    "phone",
    "post",
    "qualification"
})
@XmlRootElement(name = "Employee")
public class Employee {
    @XmlElement(required = true)
    protected String name;
    protected SexT sex;
    @XmlElement(required = true)
    protected List<PhonecodeT> phone;
    protected List<String> post;
    protected List<QualificationT> qualification;
    /**
     * Gets the value of the name property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getName() {
        return name;
    }
    /**
     * Sets the value of the name property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setName(String value) {
        this.name = value;
    }
    /**
     * Gets the value of the sex property.
     * 
     * @return
     *     possible object is
     *     {@link SexT }
     *     
     */
    public SexT getSex() {
        return sex;
    }
    /**
     * Sets the value of the sex property.
     * 
     * @param value
     *     allowed object is
     *     {@link SexT }
     *     
     */
    public void setSex(SexT value) {
        this.sex = value;
    }
    /**
     * Gets the value of the phone property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the phone property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getPhone().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link PhonecodeT }
     * 
     * 
     */
    public List<PhonecodeT> getPhone() {
        if (phone == null) {
            phone = new ArrayList<PhonecodeT>();
        }
        return this.phone;
    }
    /**
     * Gets the value of the post property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the post property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getPost().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link String }
     * 
     * 
     */
    public List<String> getPost() {
        if (post == null) {
            post = new ArrayList<String>();
        }
        return this.post;
    }
    /**
     * Gets the value of the qualification property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the qualification property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getQualification().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link QualificationT }
     * 
     * 
     */
    public List<QualificationT> getQualification() {
        if (qualification == null) {
            qualification = new ArrayList<QualificationT>();
        }
        return this.qualification;
    }
}
package com.snail.exam.jaxb;
import java.io.StringReader;
// javax.xml.bind は、JDK6 から標準添付
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import com.snail.exam.jaxb.object.Employee;
import com.snail.exam.jaxb.object.ObjectFactory;
import com.snail.exam.jaxb.object.PhonecodeT;
import com.snail.exam.jaxb.object.SexT;
public class Jaxb2Exam {
  /**
   * JAXBContext の singleton.
   */
  private static JAXBContext singJaxbContext = null;
  /**
   * JAXBContext を作成する.
   * 
   * <pre>
   * JAXBContext の初期化には、非常にコストがかかるので、毎回作るのではなく、
   * singleton を使い回す様にしなければならない。
   * JAXBContext は、Thread Safe なので、複数の Thread から同時に使われても良い。
   * 
   * (Marshaller / Unmarshaller は Thread Safe でないので、プールして使い回す
   * ときにはそれなりの対処が必要)
   * 
   * @return JAXBContext
   * @throws JAXBException JAXBContextの作成に失敗
   * @see https://jaxb.dev.java.net/guide/Performance_and_thread_safety.html
   * 
   */
  private static JAXBContext getJAXBContext() throws JAXBException {
    if (singJaxbContext == null) {
      singJaxbContext = JAXBContext.newInstance("com.snail.exam.jaxb.object");
    }
    return singJaxbContext;
  }
  private static final String XML = "<?xml version=\"1.0\"?>" + "<Employee>"
      + "<name>たろう</name>" + "<sex type=\"male\"/>"
      + "<phone type=\"cell\">09012345678</phone>"
      + "<phone type=\"office\">0398765432</phone>" + "</Employee>";
  /**
   * @param args
   */
  public static void main(final String[] args) {
    try {
      // 1) XML文書を JAXB Object に変換する
      Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
      Object jaxbObject = unmarshaller.unmarshal(new StringReader(XML));
      dumpBean((Employee) jaxbObject);
      
      // 2) JAXB Object を作成する
      ObjectFactory factory = new ObjectFactory();
      
      Employee hanako = factory.createEmployee();
      hanako.setName("はなこ");
      
      SexT sex = factory.createSexT();
      sex.setType("female");
      hanako.setSex(sex);
      
      PhonecodeT phone1 = factory.createPhonecodeT();
      phone1.setType("skype");
      phone1.setValue("05055555555");
      hanako.getPhone().add(phone1);
      
      PhonecodeT phone2 = factory.createPhonecodeT();
      phone2.setType("daemon");
      phone2.setValue("06066666666");
      hanako.getPhone().add(phone2);
      
      dumpBean(hanako);
      
      // 3) JAXB Object をXMLに変換する
      Marshaller marshaller = getJAXBContext().createMarshaller();
      
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 改行とインデントを入れる
      marshaller.setProperty(Marshaller.JAXB_ENCODING, "MS932");
      
      System.out.println("-----");
      marshaller.marshal(hanako, System.out);
      
    } catch (JAXBException e) {
      e.printStackTrace();
    }
  }
  private static void dumpBean(final Employee bean) {
    System.out.println("-----");
    System.out.println("NAME :" + bean.getName());
    System.out.println("SEX  :" + bean.getSex().getType());
    for (PhonecodeT phone : bean.getPhone()) {
      System.out.println("PHONE:" + phone.getValue() + "(" + phone.getType() +")");
    }
  }
}
-----
NAME :たろう
SEX  :male
PHONE:09012345678(cell)
PHONE:0398765432(office)
-----
NAME :はなこ
SEX  :female
PHONE:05055555555(skype)
PHONE:06066666666(daemon)
-----
<?xml version="1.0" encoding="MS932" standalone="yes"?>
<Employee>
    <name>はなこ</name>
    <sex type="female"/>
    <phone type="skype">05055555555</phone>
    <phone type="daemon">06066666666</phone>
</Employee>![[smile]](image/face/smile.png)
package com.snail.exam.jaxb;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.ValidationEventLocator;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
import com.snail.exam.jaxb.object.Employee;
import com.snail.exam.jaxb.object.PhonecodeT;
public class Jaxb2ExamValidation {
  private static JAXBContext singJaxbContext = null;
  private static JAXBContext getJAXBContext() throws JAXBException {
    if (singJaxbContext == null) {
      singJaxbContext = JAXBContext.newInstance("com.snail.exam.jaxb.object");
    }
    return singJaxbContext;
  }
  private static final String XML = 
    "<?xml version=\"1.0\"?>\n"
      + "<Employee>\n" 
      + "  <name>おすぎ</name>\n" 
      + "  <sex type=\"male\"/>\n"
      + "  <sex type=\"female\"/>\n" 
      + "</Employee>\n";
  public static void main(String[] args) {
    try {
      // 4) XML文書を XML Schema チェックしながら JAXB Object に変換する
      Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
      // JAXB 1.x では、Schema検証に、unmarshaller.setValidating(true);
      // を使っていたが、JAXB 2.x では、JAXP を使う
      SchemaFactory sf = SchemaFactory
          .newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
      Schema schema = sf.newSchema(ClassLoader
          .getSystemResource("schema/Employee.xsd"));
      unmarshaller.setSchema(schema);
      // エラーを受け取るための変数
      final boolean[] hasError = new boolean[] { false }; // <- tricky
      final Map<Integer, String> errorMap = new HashMap<Integer, String>();
      // エラーイベントハンドラを unmarshaller に設定する
      // エラーが起きると errorMap に [行数,メッセージ] の形でエラー情報を格納する
      //
      // また、hasError[0] を true に書き換える( 無名class が操作できる外部の変数
      // は final 属性のみなので、このような tricky な実装になる )
      unmarshaller.setEventHandler(new ValidationEventHandler() {
        public boolean handleEvent(ValidationEvent ve) {
          if ((ve.getSeverity() == ValidationEvent.FATAL_ERROR)
              || (ve.getSeverity() == ValidationEvent.ERROR)) {
            ValidationEventLocator locator = ve.getLocator();
            hasError[0] = true;
            errorMap.put(locator.getLineNumber(), ve.getMessage());
          }
          // 最後まで検証を行う
          return true;
        }
      });
      // XML文書の読み込み
      Object jaxbObject = unmarshaller.unmarshal(new StringReader(XML));
      if (hasError[0]) {
        // エラーがあったので、その内容を表示する
        System.out.println("INPUT XML IS NOT VALID:");
        String[] lines = XML.split("\n");
        for (int cnt = 0; cnt < lines.length; cnt++) {
          System.out.println("L" + (cnt + 1) + ":" + lines[cnt]);
          if (errorMap.containsKey(cnt + 1)) {
            System.out.println("***ERROR " + errorMap.get(cnt + 1));
          }
        }
      } else {
        // エラーが無かったので、読み込み結果を表示する
        dumpBean((Employee) jaxbObject);
      }
    } catch (JAXBException e) {
      e.printStackTrace();
    } catch (SAXException e) {
      e.printStackTrace();
    }
  }
  private static void dumpBean(final Employee bean) {
    System.out.println("-----");
    System.out.println("NAME :" + bean.getName());
    System.out.println("SEX  :" + bean.getSex().getType());
    for (PhonecodeT phone : bean.getPhone()) {
      System.out.println("PHONE:" + phone.getValue() + "(" + phone.getType()
          + ")");
    }
  }
}
INPUT XML IS NOT VALID:
L1:<?xml version="1.0"?>
L2:<Employee>
L3:  <name>おすぎ</name>
L4:  <sex type="male"/>
L5:  <sex type="female"/>
***ERROR cvc-complex-type.2.4.a: Invalid content was found starting with 
element 'sex'. One of '{phone}' is expected.
L6:</Employee>
L5 に、<sex> が現れているけど、XML Schema 的には <phone> が来るべきと言っています・・・たぶん。<?xml version="1.0" encoding="UTF-8"?>
<fooResource
    xmlns="http://foo.com/schemas/settings"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://foo.com/schemas/settings
                        http://foo.com/schemas/settings.xsd">
  <config>
    <version>5.1</version>
  </config>
  <text id="target">XXビル会議室</text>
  <text id="RESVOK">{0}件予約しました。</text>
  <text id="RESVPT">{0}件中{1}件を予約しました。内容を確認してください。</text>
  <array id="prior">
    <elem>192.168.96</elem>
    <elem>192.168.97</elem>
  </array>
  <map id="rooms">
    <elem key="room101">101会議室</elem>
    <elem key="room102">102会議室</elem>
  </map>
</fooResource>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
            targetNamespace="http://foo.com/schemas/settings"
            xmlns:foo="http://foo.com/schemas/settings" >
    <xsd:element name="fooResource">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="foo:config" minOccurs="0"
                             maxOccurs="1" />
                <xsd:element ref="foo:text" minOccurs="0"
                             maxOccurs="unbounded" />
                <xsd:element ref="foo:array" minOccurs="0"
                             maxOccurs="unbounded" />
                <xsd:element ref="foo:map" minOccurs="0"
                             maxOccurs="unbounded" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="config">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="version" type="xsd:string" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="text">
        <xsd:complexType>
            <xsd:simpleContent>
                <xsd:extension base="xsd:string">
                    <xsd:attribute name="id" type="xsd:string" />
                </xsd:extension>
            </xsd:simpleContent>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="array">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="foo:elem" minOccurs="0"
                             maxOccurs="unbounded" />
            </xsd:sequence>
            <xsd:attribute name="id" type="xsd:string" />
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="map">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="foo:elem" minOccurs="0"
                             maxOccurs="unbounded" />
            </xsd:sequence>
            <xsd:attribute name="id" type="xsd:string" />
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="elem">
        <xsd:complexType>
            <xsd:simpleContent>
                <xsd:extension base="xsd:string">
                    <xsd:attribute name="key" type="xsd:string" use="optional"/>
                </xsd:extension>
            </xsd:simpleContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>