IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  자바 | XML | 오픈 소스  >

JiBX 1.2, Part 1: Java 코드를 XML 스키마로 변환

Java 데이터 모델 및 XML 문서 간 사용자 정의 변환을 통한 스키마 퀄리티 향상

developerWorks
Go to the previous page11 페이지 중 5 페이지Go to the next page

문서 옵션
PDF format - Fits A4 and Letter

PDF - Fits A4 and Letter
188 KB (29 pages)

Get Adobe® Reader®

샘플 코드


제안 및 의견
피드백

튜토리얼 평가

이 컨텐츠를 개선하기 위한 도움을 주십시오.


BindGen 사용자 정의

이 섹션에서는 BindGen 작업을 사용자 정의하여 데이터의 XML 표현을 제어하고, 이름 및 네임스페이스의 양식을 변경하고, 스키마 구조의 일부 특성을 제어하는 방법에 대해 설명한다.

BindGen 작업 사용자 정의

BindGen에서는 바인딩 및 스키마 생성과 관련된 모든 기능을 사용자 정의할 수 있다. 적용할 사용자 정의 세트는 Java 코드의 구조를 미러링한 중첩 요소로 구성된 XML 문서로 BindGen에 전달된다. Listing 6은 간단한 예제이다.


Listing 6. 간단한 사용자 정의 예제
<custom>
  <package name="org.jibx.starter" property-access="true">
    <class name="Address" includes="street1 street2 city state postCode country"/>
    <class name="Item" excludes="description"/>
  </package>
</custom>

이 예제는 단일 Java 코드 패키지와 작동하므로 Listing 6에서는 루트 <custom> 요소의 자식 요소인 <package> 요소만 사용한다. <package><class> 사용자 정의 요소는 바깥쪽 <package> 요소에 상대적인 이름 속성을 사용하므로 Listing 6 예제에서는 각 <class> 요소에 간단한 클래스 이름 한 개가 필요하다. <package> 요소는 서로 중첩될 수 있으므로 패키지 계층 구조 내의 여러 곳에서 사용되는 클래스를 처리할 때 중첩된 <package> 요소를 사용하여 옵션을 쉽게 처리할 수 있다. 중첩 구조는 특히 많은 사용자 정의 속성이 요소 중첩을 통해 상속되기 때문에 편리하다. 이 주제는 이 섹션의 후반부에서 설명한다. 하지만 중첩의 사용은 선택적이므로 원하는 경우, <package> 요소를 하나도 사용하지 않고 완전한 클래스 이름을 가진 <class> 요소를 직접 사용할 수 있다.

사용자 정의 파일은 -c file-path 형식을 사용하여 명령행 매개변수로 BindGen에 전달된다. 사용자 정의는 항상 선택 사항이므로 기본 BindGen 동작을 변경하지 않을 경우에는 사용자 정의 파일을 사용하지 않아도 된다.




위로


코드 처리 방법 제어

BindGen은 기본적인 Java 클래스 처리 작업을 효과적으로 처리하지만 사용자의 지시 없이 수행할 수 있는 작업이 제한되어 있다. 예를 들어, 기본 처리에서는 정적, 임시 또는 최종 필드를 제외한 모든 필드가 XML 표현에 포함된다. 이 방법은 간단한 데이터 오브젝트를 나타내는 클래스의 경우 적용되지만 클래스에 상태 정보나 계산된 값이 포함된 경우에는 클래스 외부에 노출하지 않으려는 값이 XML 표현에 포함될 수 있다.

사용자 정의를 통해 BindGen이 XML 표현에 사용할 내용을 두 가지 방법으로 제어할 수 있다. 첫 번째 방법은 필드에 직접 액세스하는 대신 bean 양식의 getXXX(), setXXX()isXXX() 액세스 메소드를 사용하는 것이며, 두 번째 방법은 클래스에 대한 XML 표현에 포함할 값을 표시할지 또는 제외할 값을 표시할지 여부를 선택하는 것이다. Listing 6 사용자 정의에서는 이러한 기술을 보여 준다.

단방향 변환

이 튜토리얼에서는 JiBX를 사용하여 Java 데이터 구조와 XML 문서 사이의 양방향 변환을 수행한다. BindGen에서는 단방향 변환도 생성할 수 있으며 이 변환이 양방향 변환보다 편리한 경우도 있다. 예를 들어, 값 오브젝트 클래스는 일반적으로 변경 불가능하고 final 필드와 읽기("get") 액세스 메소드만 정의하기 때문에 BindGen을 사용하여 양방향 변환을 수행할 때 값 오브젝트 클래스를 사용하기가 어렵다. 대신 출력 전용 변환만 생성하도록 지정하면 사용자의 선택에 따라 필드 또는 특성 작업을 쉽게 수행할 수 있다. 단방향 변환을 생성하려면 사용자 정의의 루트 <custom> 요소에 direction="output" 또는 direction="input"을 사용한다.

Listing 6<package> 요소에 포함된 property-access="true" 속성은 BindGen에게 XML 표현에 포함할 값을 결정할 때 필드 대신 static이 아닌 public 액세스 메소드에서 정의한 bean 양식 특성을 찾도록 지시한다. 이 속성은 해당 속성을 가지고 있는 요소 내에서 중첩된 모든 항목에 적용되는 상속된 사용자 정의 설정을 보여 주는 예이다. Listing 6 예제에서는 두 개의 중첩된 <class> 요소에 설정이 적용된다. 또한 이 설정은 패키지의 다른 모든 클래스에 <class> 사용자 정의 요소가 없더라도 다른 모든 클래스에 적용된다. 클래스 표현에서 값을 찾는 방법을 지정하는 것 외에도 property-access 설정은 생성된 JiBX 코드에서 필드를 통해 직접적으로 또는 액세스 메소드를 호출하여 간접적으로 값에 액세스할지 여부도 제어한다.

Listing 6의 첫 번째 <class> 요소는 includes="street1 street2 city state postCode country" 속성을 사용하여 XML 표현에 포함해야 하는 클래스의 특정 값을 표시한다. 두 번째 <class> 요소는 excludes="description" 속성을 사용하여 XML 표현에서 제외할 값을 표시한다. 필드 액세스가 아닌 특성 액세스를 값에 사용하고 있기 때문에 이러한 이름은 get/set/is 액세스 메소드로 정의된 특성과 일치한다. 필드를 사용했다면 값 이름이 필드 이름과 일치하게 된다.

custgen1 Ant 대상은 Listing 6 사용자 정의를 사용하여 BindGen을 실행한다. 이 대상은 앞에서 설명한 bindgen 대상의 대체 항목이므로 Ant 명령행 ant compile custgen1 bind를 사용하여 전체 빌드를 실행한다. Listing 7에서는 이 대상이 실행될 때 생성되는 스키마의 항목 유형 정의를 보여 준다.


Listing 7. 사용자 정의된 스키마 출력의 일부
<xs:element name="item" minOccurs="0" maxOccurs="unbounded">
  <xs:complexType>
    <xs:sequence>
      <xs:element type="xs:string" name="id" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:int" use="required" name="quantity"/>
    <xs:attribute type="xs:float" use="required" name="price"/>
  </xs:complexType>
</xs:element>

Listing 7을 보면 사용자 정의에서 지정한 대로 스키마 표현에 description 값이 누락되었음을 알 수 있다.

원래 XML에 있는 <description> 요소가 더 이상 사용되지 않기 때문에 이 사용자 정의를 사용할 때 다른 XML 문서를 입력으로 사용해야 한다. Ant run1 대상은 data1.xml을 입력으로 사용하고 out1.xml을 출력으로 생성하는 테스트 프로그램을 실행한다. custom1 Ant 대상을 사용하여 소스 코드를 컴파일하는 단계부터 테스트 프로그램을 실행하는 단계까지의 전체 시퀀스를 실행할 수도 있다.

인스턴스 생성 제어

언마샬링 동안 수행되는 인스턴스 생성도 사용자 정의를 사용하여 제어할 수 있다. 기본적으로 JiBX는 각 클래스에 인수가 없는 기본 생성자가 정의되어 있다고 가정하며, 이 경우 다른 생성자가 정의되어 있지 않으면 Java 컴파일러가 인스턴스를 자동으로 생성한다. 언마샬링 동안 클래스의 새 인스턴스가 필요한 경우, JiBX는 인수가 없는 해당 생성자를 사용하여 인스턴스를 생성한다. 일부 클래스에 인수가 있는 생성자만 정의되어 있는 경우에는 BindGen 사용자 정의를 사용하여 JiBX에서 이러한 생성자를 사용할 수 있도록 만들 수 있다. 이를 수행하는 한 가지 방법은 <class> 사용자 정의 요소의 factory="xxx" 속성을 통해 클래스의 인스턴스를 생성하는 데 사용할 factory 메소드를 정의하는 것이다. 이 메소드는 클래스의 인스턴스를 리턴하는 static 메소드의 완전한 이름(패키지 및 클래스 정보 포함)을 제공한다. 또한 add-constructors="true"를 루트 <custom> 요소에 추가할 수 있다. 이렇게 하면 필요에 따라 인수가 없는 생성자를 클래스에 추가하는 바인딩이 생성된다. 이 두 번째 방법은 일반적인 데이터 클래스에 적용되지만 직접 생성할 수 없는 인터페이스 또는 추상 클래스의 경우 factory를 제공해야 한다. 물론, 출력 전용 바인딩(단방향 변환 사이드바 참조)을 생성할 경우에는 인스턴스 생성이 문제가 되지 않기 때문에 생성자를 고려하지 않아도 된다.

입력 클래스 작업을 위한 기타 사용자 정의

BindGen은 Java 입력 클래스 작업 방법을 제어하는 데 사용되는 다른 많은 사용자 정의를 지원한다. 예를 들어, Java 필드 이름에 대한 이름 변환을 사용하는 경우 strip-prefixes 또는 strip-suffixes 속성을 사용하여 특정 접두어 또는 접미어를 무시하도록 BindGen을 구성할 수 있다. (앞에 오는 m_s_ 접두어를 무시하려는 경우 strip-prefixes="m_ s_"를 사용할 수 있다.) 필드 이름에 대한 이러한 수정은 필드를 다른 사용자 정의에 사용되는 값 이름과 비교하기 전에 적용되며 XML 이름이 필드 이름에서 생성될 때도 당연히 적용된다.

클래스에 있는 개별 필드 또는 bean 특성에 대한 처리도 중첩된 <value> 요소를 사용하여 사용자 정의할 수 있다. 이러한 값 사용자 정의 요소에 관한 작업 방법에 대해서도 나중에 예를 들어 설명한다.




위로


XML 표현 제어

BindGen에서 Java 코드를 해석하는 방법을 제어하는 것 외에도 사용자 정의를 사용하여 데이터의 XML 표현을 제어할 수 있다. 이러한 XML 사용자 정의는 값의 실제 표현(요소 또는 속성), 요소 및 속성의 순서 및 이름, 선택적 또는 필수 값인지 여부 등을 포함한다.

앞에서 설명한 Listing 6 사용자 정의 예제에서는 첫 번째 <class> 요소에 사용된 includes="street1 street2 city state postCode country" 형식의 XML 사용자 정의를 살펴보았다. 이 사용자 정의가 XML 표현에 포함된 클래스의 값을 선택하는 방법에 대해 설명했다. 또한 이 사용자 정의는 값의 표시 순서가 XML 표현에 표시되는 순서가 되도록 XML 표현을 제어한다. 이는 XML에서 항상 정렬되지 않는 것으로 간주되는 속성에는 중요한 문제가 아니지만 요소에는 중요한 문제이다.

<class> 사용자 정의에서 includes 속성을 사용하여 값의 순서를 지정하지 않은 경우 BindGen은 클래스의 Java 리플렉션을 사용하여 전달되는 순서대로 값을 생성한다. 대부분의 Java 컴파일러 및 JVM에서는 이 리플렉션 순서가 Java 소스 코드에 있는 정의의 순서와 일치한다. 하지만 Java 컴파일러 및 JVM은 소스 코드의 이 순서를 유지할 필요가 없기 때문에 일부 컴파일러 또는 JVM에서는 BindGen이 하위 요소의 순서를 변경할 수도 있다. Java 컴파일러 및 JVM의 영향을 받지 않고 항상 동일한 XML 표현을 사용하려는 경우 includes 속성을 사용하여 순서를 쉽게 고정할 수 있다.

includes 속성을 사용하여 값의 XML 표현도 제어할 수 있다. BindGen에서는 표현을 표시하기 위해 앞에 오는 플래그 문자를 목록의 각 이름에 사용할 수 있다. 예를 들어, @는 속성을 나타내고 /는 속성을 나타낸다. 따라서 Listing 6 사용자 정의를 includes="street1 street2 city state @postCode country"로 변경하면 우편 번호 값의 표현이 하위 요소에서 속성으로 변경된다.

필수 상태 제어

선택적 또는 필수 값인지 여부를 제어하는 것도 <class> 요소의 requiredsoptionals 속성을 사용하여 수행할 수 있는 또 하나의 쉬운 사용자 정의이다. includes 속성을 사용할 때와 같이 requiredsoptionals 목록에 있는 이름 앞에 플래그 문자를 지정하여 하위 요소 또는 속성으로 표현해야 하는지 여부를 나타낼 수 있다.

기본적으로 BindGen은 모든 원시 값과 단순 오브젝트 값(String이 아닌 직접 XML 해당 유형을 가진 클래스)을 속성으로 간주하고 모든 복합 오브젝트 값을 하위 요소로 간주한다. 모든 원시 값은 필수 값으로 간주되고 모든 오브젝트 값은 선택적 값으로 간주된다. <class> 사용자 정의에서 includes, requiredsoptionals 요소를 사용하여 이러한 기본값을 재정의하는 방법뿐 아니라 임의 레벨의 사용자 정의(<custom>, <package> 또는 <class> 요소)에서 value-style="element" 속성을 설정하여 모든 값에 대한 요소를 사용할 기본 표현을 변경할 수 있다. require 속성을 사용하여 XML에서 필수 값으로 간주해야 하는 유형을 제어할 수도 있다.

  • require="none"은 모든 값을 선택적 값으로 만든다.
  • require="primitives"는 원시 값만 필수 값으로 만든다(기본값).
  • require="objects"는 기본값과 반대로 원시 값을 선택적 값으로 만들고 오브젝트 유형을 필수 값으로 만든다.
  • require="all"은 기본적으로 모든 값을 필수 값으로 간주한다.

Listing 8에서는 튜토리얼 다운로드의 dwcode1 디렉토리에 있는 custom2.xml 사용자 정의 파일을 보여 준다. 이 파일의 일부 기능은 이 섹션의 앞 부분에서 이미 설명했다.


Listing 8. 순서, 필수 상태 및 표현 사용자 정의
<custom property-access="true">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="/orderNumber customer billTo shipping orderDate"/>
  </package>
</custom>

Ant custgen2 대상을 사용하여 이 사용자 정의 세트를 시도할 수 있다. 전체 빌드를 실행하려면 ant compile custgen2 bind를 사용한다. Listing 9에서는 이러한 사용자 정의를 사용하여 생성된 스키마의 특정 부분을 보여 준다. 이 Listing에서는 결과 순서, 필수 상태(선택적 요소에 minOccurs="0"을 사용하면 스키마에 기본적으로 필요한 요소가 되고, 필수 속성에 use="required"를 사용하면 스키마에서 기본적으로 선택적 속성이 됨) 및 요소 또는 속성 표현을 보여 준다.


Listing 9. 사용자 정의를 사용하여 생성된 스키마
<xs:complexType name="order">
  <xs:annotation>
    <xs:documentation>Order information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
    <xs:element type="xs:long" name="orderNumber">
      <xs:annotation>
        <xs:documentation>Get the order number.</xs:documentation>
      </xs:annotation>
    </xs:element>
    <xs:element name="customer">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:long" name="customerNumber"/>
          <xs:element type="xs:string" name="firstName"/>
          <xs:element type="xs:string" name="lastName"/>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
    ...
  </xs:sequence>
  <xs:attribute type="xs:date" use="required" name="orderDate"/>
  <xs:attribute type="xs:date" name="shipDate"/>
  <xs:attribute type="xs:float" name="total"/>
</xs:complexType>
<xs:element type="tns:order" name="order"/>
<xs:complexType name="address">
  <xs:annotation>
    <xs:documentation>Address information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
    <xs:element type="xs:string" name="street1"/>
    <xs:element type="xs:string" name="street2" minOccurs="0"/>
    <xs:element type="xs:string" name="city"/>
    <xs:element type="xs:string" name="country" minOccurs="0"/>
  </xs:sequence>
  <xs:attribute type="xs:string" name="state"/>
  <xs:attribute type="xs:string" name="postCode"/>
</xs:complexType>

bind Ant 태스크를 사용하여 바인딩을 컴파일한 후에는 data2.xml 테스트 문서를 입력으로 받아서 out2.xml 출력 파일을 생성하는 run2 태스크를 사용하여 이 바인딩을 테스트할 수 있다. 컴파일 단계부터 custom2 대상을 테스트하는 단계까지의 전체 시퀀스를 실행할 수도 있다. Listing 10에서는 테스트 문서를 보여 준다.


Listing 10. 사용자 정의와 일치하는 테스트 문서
<order orderDate="2008-10-18" shipDate="2008-10-22" xmlns="http://jibx.org/starter">
  <orderNumber>12345678</orderNumber>
  <customer>
    <customerNumber>5678</customerNumber>
    <firstName>John</firstName>
    <lastName>Smith</lastName>
  </customer>
  <billTo state="WA" postCode="98059">
    <street1>12345 Happy Lane</street1>
    <city>Plunk</city>
    <country>USA</country>
  </billTo>
  <shipping>PRIORITY_MAIL</shipping>
  <shipTo state="WA" postCode="98034">
    <street1>333 River Avenue</street1>
    <city>Kirkland</city>
  </shipTo>
  <item quantity="1" price="5.99" id="8394983498512"/>
  <item quantity="2" price="9.50" id="9912349050499"/>
  <item quantity="1" price="8.95" id="1293000488209"/>
</order>

Listing 10Listing 3의 원래 테스트 문서를 비교하여 사용자 정의에 의해 데이터의 XML 표현이 어떻게 변경되었는지 확인할 수 있다. 예를 들어, 행 항목의 양식이 원래 표현보다 좀 더 간결한 표현인 빈 요소로 변경되었다는 것을 알 수 있다.




위로


이름 및 네임스페이스 제어

Java 이름은 관례상 이름을 소문자로 표시하고 각 단어의 첫 번째 글자만 대문자로 표시하는 "낙타 표기법" 양식을 사용한다. 필드 또는 특성 이름의 경우에는 두 번째 단어의 첫 번째 문자부터 대문자로 표시한다(예: postCodecustomerNumber). XML 이름은 아직 표준화되지 않았으며 여러 가지 다양한 양식이 사용되고 있다. 즉, 첫 번째 문자를 소문자로 표시하는 낙타 표기법 양식(Java 필드 및 특성 이름 양식), 첫 번째 문자를 대문자로 표시하는 낙타 표기법 양식(Java 클래스 이름 양식), 하이픈 구분자 양식(하이픈으로 단어 구분), 점 구분자 양식(마침표로 단어 구분) 및 밑줄 구분자 양식(밑줄로 단어 구분)이 있다.

BindGen은 기본적으로 낙타 표기법 양식의 XML 이름을 사용하는 것으로 가정하지만 임의의 사용자 정의 레벨(<custom>, <package> 또는 <class> 요소)에서 name-style 속성을 설정하여 이름에 사용할 양식을 쉽게 변경할 수 있다. 이 속성에 사용할 수 있는 값은 다음과 같이 위에서 설명한 여러 XML 양식과 일치한다.

  • camel-case(기본값)
  • upper-camel-case
  • hyphenated
  • dotted
  • underscored

값에 대한 사용자 정의를 사용하여 값의 XML 이름을 설정할 수도 있다. 개별 값 사용자 정의를 사용하면 값에 액세스하는 방법과 XML에서 값을 표현하는 방법을 모두 제어할 수 있다. Listing 11에서는 앞의 예제에 표시된 코드와 동일한 예제 코드를 기반으로 개별 값에 사용자 정의 요소를 사용하는 예제를 보여 준다.


Listing 11. 이름 및 네임스페이스 사용자 정의
<custom property-access="true" name-style="hyphenated" namespace="http://jibx.org/custom"
    namespace-style="fixed">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="orderNumber customer billTo shipping orderDate">
     <value property-name="orderNumber" element="order-num"/>
      <value property-name="items" item-name="line-item" element="order-items"/>
    </class>
  </package>
</custom>

Listing 11의 첫 번째 사용자 정의는 <class name="Order"...> 요소에 있는 orderNumber 특성에 대한 것이다. orderNumber 사용자 정의는 element="order-num" 속성을 사용하여 BindGen에게 값을 원시 값에 사용되는 기본 속성 형식이 아닌 요소로 표현하도록 지시한다. 두 번째 사용자 정의는 items 콜렉션 특성에 대한 것이다. 이 사용자 정의는 item-nameelement 속성을 사용한다. item-name 속성은 콜렉션이 표현하는 개별 값에 사용되는 이름을 제어하는 반면 element 속성은 제공된 이름을 콜렉션에 있는 값 주위의 랩퍼 요소로 사용한다.

네임스페이스가 없는 XML

네임스페이스의 사용이 일반적으로 가장 효과적인 데이터 교환 방법으로 간주되고 있기 때문에 이 튜토리얼의 모든 예제에서는 XML 네임스페이스를 사용한다. 네임스페이스를 사용하지 않고 XML 작업을 수행하려면 임의의 사용자 정의 레벨에서 namespace-style="none" 속성을 사용하여 모든 중첩된 구성 요소에 네임스페이스를 사용하지 않도록 설정한다.

Listing 11 사용자 정의에서는 XML 문서에서 사용할 네임스페이스도 정의한다. 이전 예제에서는 BindGen에서 기본적으로 제공되는 네임스페이스 처리 기능을 사용했다. 이 방법은 Java 코드의 XML 표현에 사용되는 네임스페이스 URI를 Java 패키지에서 가져온다. 이 기본 처리 기능은 org.jibx.starter 패키지를 네임스페이스 URI http://jibx.org/starter로 변환했다. Listing 11에서는 namespace="http://jibx.org/custom"namespace-style="fixed" 속성 쌍을 루트 <custom> 요소에 추가하여 네임스페이스를 사용자 정의한다. 이들 속성 중 첫 번째 속성은 기본 네임스페이스를 정의하는 반면 두 번째 속성은 Java 패키지를 기반으로 네임스페이스를 수정하는 일반적인 동작을 금지한다. 이러한 속성은 모두 사용자 정의 요소를 중첩하여 상속되므로 <custom> 요소 대신 <package> 요소에 쉽게 배치할 수 있다.

표준 bind 대상을 사용하여 JiBX 바인딩 컴파일러를 실행한 후에 Ant custgen3 대상(바인딩 및 스키마 생성의 경우)과 run3 대상을 사용하여 Listing 11 사용자 정의를 시도하거나 full3 대상을 사용하여 전체 시퀀스를 실행할 수 있다. Listing 12에서는 테스트 코드와 함께 사용되는 입력 문서를 보여 준다.


Listing 12. 사용자 정의된 이름 및 네임스페이스를 사용하는 XML 샘플
<order order-date="2008-10-18" ship-date="2008-10-22" xmlns="http://jibx.org/custom">
  <order-num>12345678</order-num>
  <customer>
    <customer-number>5678</customer-number>
    <first-name>John</first-name>
    <last-name>Smith</last-name>
  </customer>
  <bill-to state="WA" post-code="98059">
    <street1>12345 Happy Lane</street1>
    <city>Plunk</city>
    <country>USA</country>
  </bill-to>
  <shipping>PRIORITY_MAIL</shipping>
  <ship-to state="WA" postCode="98034">
    <street1>333 River Avenue</street1>
    <city>Kirkland</city>
  </ship-to>
  <order-items>
    <line-item quantity="1" price="5.99" id="AC4983498512"/>
    <line-item quantity="2" price="9.50" id="IW2349050499"/>
    <line-item quantity="1" price="8.95" id="RC3000488209"/>
  </order-items>
</order>

Listing 12Listing 10 샘플을 비교해 보면 마지막 사용자 정의에 의해 표현이 어떻게 변경되었는지 확인할 수 있다.




위로


스키마 표현 사용자 정의

지금까지 BindGen 사용자 정의를 통해 Java 데이터의 XML 표현을 변경하는 방법을 살펴보았다. 사용자 정의는 실제 스키마 구조의 일부 기능을 제어하는 경우에도 사용할 수 있다.

BindGen은 기본적으로 전역 유형 및 요소보다는 중첩된 정의를 사용한다. Listing 9에서 설명한 생성된 스키마를 다시 보면 이 중첩 구조를 볼 수 있다. 이 스키마에서는 세 개의 전역 정의 즉, addressorder 복합 유형과 order 요소만 사용한다. Java 데이터 구조의 다른 클래스(Customer, ItemShipping)는 Order 클래스에서 한 번씩만 참조되므로 해당 유형 정의가 order 스키마 유형 정의 안에 직접 포함된다.

임의의 중첩 사용자 정의 요소의 force-mapping="true" 속성을 사용하여 스키마 양식을 변경할 수 있다. Listing 13에서는 이 변경 사항을 Listing 9의 생성된 스키마와 일치하는 custom2.xml 사용자 정의에 추가하는 custom4.xml 사용자 정의 파일을 보여 준다.


Listing 13. 스키마 구조의 사용자 정의
<custom property-access="true" force-mapping="true">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="/orderNumber customer billTo shipping orderDate"/>
  </package>
</custom>

Listing 14에서는 custgen4 Ant 대상을 실행하여 starter.xsd로 생성된 결과 스키마 구조를 보여 준다. 이 버전의 스키마는 Listing 9 스키마와 동일한 XML 문서 구조를 나타내지만 각 Java 클래스에 해당하는 별도의 유형 정의가 포함되어 있다.


Listing 14. 사용자 정의된 스키마 구조
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://jibx.org/starter" elementFormDefault="qualified"
    targetNamespace="http://jibx.org/starter">
  <xs:simpleType name="shipping">
    <xs:annotation>
      <xs:documentation>Supported shipment methods. The "INTERNATIONAL" shipment
      methods can only be used for orders with shipping addresses outside the U.S., and
      one of these methods is required in this case.</xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:string">
      ...
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="item">
    <xs:annotation>
      <xs:documentation>Order line item information.</xs:documentation>
    </xs:annotation>
    <xs:sequence/>
    <xs:attribute type="xs:string" use="required" name="id"/>
    <xs:attribute type="xs:int" use="required" name="quantity"/>
    <xs:attribute type="xs:float" use="required" name="price"/>
  </xs:complexType>
  <xs:element type="tns:order" name="order"/>
  <xs:complexType name="address">
    <xs:annotation>
      <xs:documentation>Address information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:string" name="street1"/>
      <xs:element type="xs:string" name="street2" minOccurs="0"/>
      <xs:element type="xs:string" name="city"/>
      <xs:element type="xs:string" name="country" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="state"/>
    <xs:attribute type="xs:string" name="postCode"/>
  </xs:complexType>
  <xs:complexType name="customer">
    <xs:annotation>
      <xs:documentation>Customer information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:long" name="customerNumber"/>
      <xs:element type="xs:string" name="firstName"/>
      <xs:element type="xs:string" name="lastName"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="order">
    <xs:annotation>
      <xs:documentation>Order information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:long" name="orderNumber">
        <xs:annotation>
          <xs:documentation>Get the order number.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="tns:customer" name="customer"/>
      <xs:element type="tns:address" name="billTo"/>
      <xs:element type="tns:shipping" name="shipping"/>
      <xs:element type="tns:address" name="shipTo" minOccurs="0"/>
      <xs:element type="tns:item" name="item" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute type="xs:date" use="required" name="orderDate"/>
    <xs:attribute type="xs:date" name="shipDate"/>
    <xs:attribute type="xs:float" name="total"/>
  </xs:complexType>
</xs:schema>

Listing 14에서 보여 준 유형의 스키마를 "베니션 블라인드" 양식 스키마라고 하며 복잡한 XML 구조 정의를 표현할 때 자주 사용된다. 이 스키마 양식을 사용하면 각 유형 정의를 구분할 수 있기 때문에 스키마를 수정 또는 확장할 때 구성 요소 구조를 쉽게 다시 사용할 수 있다. Java 코드를 기반으로 후속 변경 작업을 수행하려는 경우에는(코드를 변경할 때마다 BindGen을 다시 실행함) 베니션 블라인드 양식의 유연성이 별로 도움이 되지 않겠지만 스키마를 기반으로 후속 개발 작업을 진행할 경우에는 많은 도움을 받을 수 있다.




위로



Go to the previous page11 페이지 중 5 페이지Go to the next page
    IBM 소개 개인정보 보호정책 문의