IBM Korea Skip to main content
       IBM 홈    |  제품 & 서비스  |  고객지원 & 다운로드  |  회원가입  

Schema Infoset Model로 XML 스키마 분석하기
Schema Infoset Model로 스키마에 대한 복잡한 쿼리를 간단히!

Level: Intermediate

Shane Curcuru
Advisory Software Engineer, IBM
June 2002

스키마(Schema)가 복잡해지면 스키마를 조작할 툴에 대한 필요도 많아지게 된다. 새로운 Schema Infoset Model은 스키마 자체의 완벽한 모델링 뿐만 아니라 구체적인 구현과 스키마 또는 스키마 세트에서의 추상 관계를 보여준다. 이 글에서는 스키마 모델을 쉽게 요청할 수 있는 라이브러리를 설명한다. 모든 문제를 해결하도록 스키마를 업데이트 할 수 있는 방법도 제시한다.

Note: 이 글은 스키마 문서에 대해 기본적인 지식을 갖고있다는 전제하에 작성되었다. 참고자료에서 스키마 문서와 튜토리얼 정보를 참조하기 바란다.

XML 문서를 검증하고 분석하는 스키마(Schema)를 사용하는 파서와 툴들은 많이 있어도 질의와 스키마 문서의 고급 조작 툴은 여전히 구현되고 있다. Schema Infoset Model (AKA the IBM Java Library for Schema Components 또는 "라이브러리")는 스키마를 모델링하는 풍부한 API 라이브러리를 제공한다. 스키마 스팩을 읽어본 사람이면 누구나 알겠지만 매우 자세하고 이 모델은 어떤 스키마에서라도 모든 세부사항을 노출한다. 이렇게 되면 스키마 콜렉션을 효율적으로 관리할 수 있다.

Schema Infoset Model UML 다이어그램

이 라이브러리에는 실제 라이브러리 클래스를 위한 다양한 UML 다이어그램이 있다. 일반적인 스키마 컴포넌트의 관계 및 속성을 빠르게 설명해준다.

Abstract Schema Component 관계
이 다이어그램은 Schema Infoset Component 들의 관계를 보여준다; 라이브러리에 모델링 될 때 스키마 객체들 사이의 추상 관계이다. 검은 다이아몬드는 강력한 결합을 의미한다. 개방된 다이아몬드는 약한 결합을 나타낸다.

Abstract Schema Component 속성
이 다이어그램은 라이브러리에 모델링 될 때 추상 스키마 컴포넌트의 속성은 물론 클래스 계층의 일부를 보여준다.

이 다이어그램들은 라이브러리 문서에 포함되어있다. 추상 클래스와 구체적인 클래스 트리를 위한 UML 다이어그램도 있다.

모델링 된 모든 스키마 객체들을 보여주는 라이브러리의 인터페이스 목록은 Schema Infoset Model UML 다이어그램을 참조하기 바란다. 이 라이브러리에는 라이브러리 인터페이스를 구현하는데 사용되는 UML 다이어그램이 포함되어 있다. 이 다이어그램은 라이브러리 객체들의 관계를 보여주어 스키마 스팩의 개념들을 매우 유사하게 모방한다.

예제: 스키마 분석하기
이 예제에서 integer-derived 유형 제한을 설정하는 것을 실패할 경우의 스키마를 점검하기를 원할 것이다. 이것은 구매 주문서의 구매량이 늘어났다는 것을 확인하기에 유용하다. 여기에서 스키마는 매우 구체적이고 min/maxInclusive 또는 min/maxExclusive Facet 정수 에서 얻어진 모든 간단한 유형들이 포함되어야한다.

XSLT 또는 XPath를 사용하여 .xsd 파일 또는 다른 .xml 내용안에 스키마의 구체적인 구현을 쿼리할 수는 있지만 스키마 컴포넌트가 실제로 갖고 있는 유형도출과 상호 관계를 발견하기가 훨씬 어려워진다. Schema Infoset Model 라이브러리는 스키마의 구체적 구현과 추상 개념 모두를 모델링하기 때문에 컴포넌트에 대한 자세한 사항을 수집할 때 쉽게 사용할 수 있다.

다음의 간단한 스키마에서 max/min facet 기준에 부합하는 몇 가지 유형을 보게 될 것이다. 어떤 것은 그렇지 않은 것도 있다. ( zip file에 있는 FindTypesMissingFacets.xsd에서 완전한 스키마를 찾을 수 있다.)

Listing 1. 샘플 스키마

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.research.ibm.com/XML/NS/xsd"
xmlns="http://www.research.ibm.com/XML/NS/xsd">

<!-- SimpleType missing both max/min facets -->
<xsd:simpleType name="integer-noFacets">
    <xsd:restriction base="xsd:integer"/>
</xsd:simpleType>

<!-- Derived type has inherited min facet but missing max facet -->
<xsd:simpleType name="positiveInteger-inheritedMinFacet">
    <xsd:restriction base="xsd:positiveInteger"/>
</xsd:simpleType>

<!-- Derived type with both effective max/min facets -->
<xsd:simpleType name="positiveInteger-bothFacets">
    <xsd:restriction base="positiveInteger-inheritedMinFacet">
        <xsd:maxExclusive value="100"/>
    </xsd:restriction>
</xsd:simpleType>
<!-- etc... -->
</xsd:schema>

스키마를 라이브러리에 로딩하기
라이브러리가 다양한 소스에서 스키마 객체를 읽고 쓸 수 있다. IBM WebSphere EMF ResourceSet 프레임웍을 사용하여 스키마 세트를 쉽게 로딩하는 방법을 설명하겠다. DOM 객체에 직접 스키마를 구현하고 DOM 객체에서 스키마를 방출할 수 있다. 라이브러리는 XSDResourceSet 이라는 커스텀 구현을 제공하는데 이는 include, import, redefine에 의해 관련된 스키마 세트를 지능적이고 자동적으로 로딩한다. 관련 스키마들 사이의 추상 관계도 이 라이브러리에서 모델링된다.

Listing 2. 스키마 로딩하기

// String variable schemaURL is "FindTypesMissingFacets.xsd" or the URL to your schema
// Create a resource set and load the main schema file into it.
ResourceSet resourceSet = new ResourceSetImpl();
XSDResourceImpl xsdSchemaResource = (XSDResourceImpl)resourceSet.load(schemaURL);

// getResources() returns an iterator over all the resources, therefore, the main resource
// and those that have been included, imported, or redefined.
for (Iterator resources = resourceSet.getResources().iterator(); 
    resources.hasNext(); /* no-op */)
{
    // Return the first schema object found, which is the main schema 
    //   loaded from the provided schemaURL
    Resource resource = (Resource)resources.next();
    if (resource instanceof XSDResourceImpl)
    {
        XSDResourceImpl xsdResource = (XSDResourceImpl)resource;
        // This returns a com.ibm.etools.xsd.XSDSchema object
        return xsdResource.getSchema();
    }
}

간편한 스키마 쿼리
XSDSchema 객체가 있으므로 max/min facet이 없는 모든 유형을 찾기위해 이를 쿼리해야 한다. 우선 편리한 라이브러리 메소드를 사용하여 빌트인 정수 타입에서 유출한 모든 simpleTypeDefinition을 빠르게 찾는다. 라이브러리가 스키마의 추상 의미의 완벽한 모델을 제공하기 때문에 매우 간단하다. getTypeDefinitions()을 위해 XSDSchema를 쿼리하고 기본 정수 타입에서 상속받은 XSDSimpleTypeDefinition를 위해 필터링한다.

Listing 3. 구체적 유형 리스트 얻기

// A handy convenience method quickly gets all 
//   typeDefinitions within the schema
List allTypes = schema.getTypeDefinitions();
ArrayList allIntegerTypes = new ArrayList();

for (Iterator iter = allTypes.iterator(); 
        iter.hasNext(); /* no-op */)
{
    XSDTypeDefinition typedef = (XSDTypeDefinition)iter.next();
    // Filter out for only simpleTypes...
    if ((typedef instanceof XSDSimpleTypeDefinition) 
        // ... and filter for built-in integer types
        // Use a worker method in the very handy sample 
        //  program com.ibm.etools.xsd.util. XSDSchemaQueryTools
        && XSDSchemaQueryTools.isTypeDerivedFrom(typedef, 
                schema.getSchemaForSchemaNamespace(), "integer"))
    {
        // The filter found one; save it and continue.
        allIntegerTypes.add(typedef);
    }
}

스키마 컴포넌트 모델
W3C 스키마 스팩에 정의된 모든 컴포넌트는 라이브러리에서 자세하게 모델링된다. 정수에서 유출한 모든 XSDSimpleTypeDefinition의 리스트가 있으므로 max 또는 min facet이 없는 것에도 이 리스트를 쿼리할 수 있다. 리포트를 만들 수도 있다. 라이브러리가 빠른 검색을 위해 max/minExclusive 또는 max/minInclusive facet을 그룹핑 할 수 있다는 것을 기억하라. 또한 각 유형 마다 자세한 액세스를 제공한다.

Listing 4. XSDSimpleType 컴포넌트 쿼리

for (Iterator iter = allIntegerTypes.iterator(); 
        iter.hasNext(); /* no-op */)
{
    XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition)iter.next();
    // First, exclude any UNION or LIST types, since 
    //  the schema spec says they can't have min/max facets:
    //  Part 2: Datatypes in:
    //  '4.1.5 Constraints on Simple Type Definition Schema Components'
    if ((XSDVariety.LIST == simpleType.getValueVariety())
        || (XSDVariety.UNION == simpleType.getValueVariety()))
    {
        // Unions and lists cannot have min/max facets at all,
        //  so there's no need to report them
        continue;
    }

    // Get the effective max/min facets for each type - 
    //  this includes ones declared in this type or 
    //  ones that are inherited, and so forth
    XSDMaxFacet maxFacet = simpleType.getEffectiveMaxFacet();
    XSDMinFacet minFacet = simpleType.getEffectiveMinFacet();

    // If you don't have the proper ones, report the error.
    if ((null == maxFacet) || (null == minFacet))
    {
        if (simpleType.isSetName())
        {
            // A component's URI in the library is effectively 
            //  its <target namespace>#<name>
            System.out.println("Schema named component: " + simpleType.getURI() );
        }
        else
        {
            // It's an anonymous type, so ask the library 
            //  to construct a default 'alias' for it
            System.out.println("Schema anonymous component: " + simpleType.getAliasURI() );
        }
        System.out.print(" is missing these required facets: ");
        if (null == maxFacet)
        {
            System.out.print(" XSDMaxFacet (either inclusive or exclusive) ");
        }
        if (null == minFacet)
        {
            System.out.print(" XSDMinFacet (either inclusive or exclusive) ");
        }
        // You could also report on the facets this type does have like:
        // if (minFacet.isExclusive) {
        // System.out.println("minFacet.getValue=" + minFacet.getValue());
        // }
    }
}

max/min facet이 없는 유형
몇 개의 코드를 가지고 스키마에 대한 매우 상세한 정보를 발견했다. 샘플 코드를 다운로드 하여 제공된 스키마 파일에 대해 실행하면 다음과 같은 리스트가 나온다:

Listing 5. 결과

Schema missing max/min facet report on: FindTypesMissingFacets.xsd
Schema named component: http://www.research.ibm.com/XML/NS/xsd#integer-minFacet
  is missing these required facets:  XSDMaxFacet (either inclusive or exclusive)

Schema named component: http://www.research.ibm.com/XML/NS/xsd#integer-noFacets
  is missing these required facets:  XSDMaxFacet (either inclusive or exclusive)
  XSDMinFacet (either inclusive or exclusive)

Schema named component: http://www.research.ibm.com/XML/NS/xsd#positiveInteger-inheritedMinFacet
  is missing these required facets:  XSDMaxFacet (either inclusive or exclusive)

결론
라이브러리의 상세한 스키마 구현으로, 필요로하는 스키마 부분을 정학히 찾을 수 있다는 것을 설명했다. 이 라이브러리는 스키마 컴포넌트용 세터 메소드(setter method)를 제공하여 샘플 코드를 쉽게 업데이트하여 유실된 facet을 추가하여 발견된 모든 유형을 자동으로 고칠 수 있다. 그리고 라이브러리는 스키마의 구체적인 구현을 모델링하기 때문에 업데이트 된 스키마를 .xsd 파일에 다시 작성할 수 있다.

샘플 코드
샘플 프로그램인, XSDFindTypesMissingFacets.java는 이 글을 위한 특별한 예제였다. max/min facet을 가지고 있거나 그렇지 않은 많은 유형을 포함한 FindTypesMissingFacets.xsd 스키마 문서를 사용한다.

샘플 프로그램과 zip file에 있는 .java 파일을 다운로드 할 수 있다.

Schema Infoset Model과 함께 제공되는 기타 여러 .java 파일 샘플의 복사본은 다음과 같다:

  • XSDSchemaQueryTools.java는 스키마 객체에 대한 향상된 쿼리를 수행하는 다른 방식들을 보여준다.
  • XSDSchemaBuildingTools.java : 스키마를 프로그램으로 구현하는 편리한 메소드 포함.
  • XSDPrototypicalSchema.java : primer PurchaseOrder sample 스키마를 구현하는 라이브러리 사용.

참고자료

목 차:
예제: 스키마 분석하기
스키마 로딩하기
간편한 스키마 쿼리
스키마 컴포넌트 모델
max/min facet이 없는 유형
결론
샘플 코드
참고 자료
필자 소개
기사에 대한 평가
관련 dW 링크:
The basics of using XML Schema to define elements
Referencing XML schemas
Subscribe to the developerWorks newsletter
US 원문 읽기
Also in the XML zone:
Tutorials
Tools and products
Code and components
Articles
Also in the Java zone:
Tutorials
Tools and products
Code and components
Articles
필자소개
Shane Curcuru는 Lotus와 IBM에서 12년 동안 개발자 및 엔지니어로 재직하고 있으며 Apache Software Foundation의 회원이다.
이 기사에 대하여 어떻게 생각하십니까?

정말 좋다 (5) 좋다 (4) 그저그렇다 (3) 수정보완이 필요하다(2) 형편없다 (1)

  회사소개  |  개인정보 보호정책  |  법률  |  문의