Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

XML スキーマの詳細オプション

この章では、XML スキーマを作成するための詳細オプションについて説明します。以下のトピックについて説明します。

この章の XML 例はリテラル形式になります。

この章で説明されているクラスとプロパティのパラメータ
  • XMLTYPECONSTRAINT

  • XMLINCLUDEINLIST

  • XMLINHERITANCE

サブクラスのタイプの自動作成

クラスの XML プロジェクションを定義すると、そのサブクラスはすべて自動的にそれぞれ別のタイプにマップされます。それらすべてのサブクラスは、基本タイプとしてスーパークラスを使用します。これは、スーパータイプが使用されるどの場所でも、サブタイプのいずれかを代わりに使用できることを意味します。また、サブタイプを使用して、XML スキーマで選択リストまたは置換グループを定義できます。

抽象クラスの XML プロジェクションを定義することもできます。抽象クラスなのでインスタンス化することはできませんが、派生クラスのスキーマでこのクラスは基本タイプとして表示されます。

例を考えてみます。単純な Person クラスから始めます。

Class UsingSubclasses.Person Extends (%Persistent, %XML.Adaptor)
{
Property Name As %String [Required];
Property DOB As %Date(FORMAT = 5, MAXVAL = "+$h") [Required];
}

Person クラスに直接基づく 2 つのクラスがあるとします。1 番目は Patient クラスです。

Class UsingSubclasses.Patient Extends UsingSubclasses.Person
{
Property PatientID As %String [Required];
}

次は Employee クラスです。

Class UsingSubclasses.Employee Extends UsingSubclasses.Person
{
Property EmployeeID As %String [Required];
}

最後に、Person をプロパティとして使用するクラスを考えてみます。

Class UsingSubclasses.Example1 Extends (%Persistent, %XML.Adaptor)
{
Property Person As UsingSubclasses.Person;
}

Example1 クラスのスキーマを生成すると、結果は以下のようになります。

<s:complexType name="Example1">
    <s:sequence>
        <s:element name="Person" type="Person" minOccurs="0" />
    </s:sequence>
</s:complexType>
<s:complexType name="Employee">
    <s:complexContent>
        <s:extension base="Person">
            <s:sequence>
                <s:element name="EmployeeID" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>
<s:complexType name="Person">
    <s:sequence>
        <s:element name="Name" type="s:string" />
        <s:element name="DOB" type="s:date" />
    </s:sequence>
</s:complexType>
<s:complexType name="Patient">
    <s:complexContent>
        <s:extension base="Person">
            <s:sequence>
                <s:element name="PatientID" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>

これから以下の点がわかります。

  • Example1 のタイプは Person です。

  • Employee タイプおよび Patient タイプがどちらも定義されています。これは既定です (参考までに、これは XMLTYPECONSTRAINT プロパティ・パラメータを "EXPLICIT" に設定することに対応します)。

  • XML スキーマの仕様により、前述のスキーマは <Person> 要素が含まれる任意の場所であり、<Employee> 要素または <Patient> 要素のいずれかを含めることができることになります。

サブタイプの選択リストの作成

XML スキーマの仕様により、複雑なタイプは、特に関連するタイプでは、タイプの選択リストで構成できます。<Person> 要素 1 つではなく、<Person><Patient>、または <Employee> の要素をスキーマで許可するとします。こうしたスキーマを定義するには、以下のように Person プロパティの XMLTYPECONSTRAINT プロパティ・パラメータを "CHOICE" に設定します。

Class UsingSubclasses.Example2 Extends (%Persistent, %XML.Adaptor)
{
Property Person As UsingSubclasses.Person(XMLTYPECONSTRAINT = "CHOICE");
}

既定では、選択リストは Person クラスのすべてのサブクラスで構成されます。Example2 のスキーマは以下のようになります。

<s:complexType name="Example2">
    <s:sequence>
        <s:choice minOccurs="0">
            <s:element name="Employee" type="Employee" />
            <s:element name="Patient" type="Patient" />
            <s:element name="Person" type="Person" />
        </s:choice>
    </s:sequence>
</s:complexType>
<s:complexType name="Employee">
    <s:complexContent>
        <s:extension base="Person">
            <s:sequence>
                <s:element name="EmployeeID" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>
<s:complexType name="Person">
    <s:sequence>
        <s:element name="Name" type="s:string" />
        <s:element name="DOB" type="s:date" />
    </s:sequence>
</s:complexType>
<s:complexType name="Patient">
    <s:complexContent>
        <s:extension base="Person">
            <s:sequence>
                <s:element name="PatientID" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>

前述の例とは対照的に、Example2 のタイプは、PersonPatient、または Employee で構成される選択リストです。後の 3 つのタイプは、前述の例と同様に定義されます。

選択リストでのサブクラスの制限

すべてのサブクラスを選択リストに含める必要がない場合があります。2 つの方法で、サブクラスのリストを制限できます。

  • XMLINCLUDEINGROUP クラス・パラメータを使用して、選択リストに含めないように、任意のサブクラスにマークを付けます。

  • XMLCHOICELIST プロパティ・パラメータを、選択リストのサブクラスのコンマ区切りのリストに設定します。

  • このパラメータは優先されます。つまり、あるサブクラスが XMLCHOICELIST に挙げられている場合は、そのサブクラス自体が XMLINCLUDEINGROUP = 0 とマークされている場合でも、選択リストに含められます。

以下のセクションに例を示します。

明示的リストを含む選択リストの例

XMLCHOICELIST プロパティ・パラメータを、選択リストに含めるサブクラスのコンマ区切りリストに設定するとします。例えば、次のようになります。

Class UsingSubclasses.Example2A Extends (%Persistent, %XML.Adaptor)
{
Property Person As UsingSubclasses.Person
(XMLCHOICELIST = "UsingSubclasses.Patient, UsingSubclasses.Employee",
XMLTYPECONSTRAINT = "CHOICE");
}

このクラスのスキーマは以下のようになります。

<s:complexType name="Example2A">
    <s:sequence>
        <s:choice minOccurs="0">
            <s:element name="Patient" type="Patient" />
            <s:element name="Employee" type="Employee" />
        </s:choice>
    </s:sequence>
</s:complexType>
<s:complexType name="Patient">
    <s:complexContent>
        <s:extension base="Person">
            <s:sequence>
                <s:element name="PatientID" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>
<s:complexType name="Person">
    <s:sequence>
        <s:element name="Name" type="s:string" />
        <s:element name="DOB" type="s:date" />
    </s:sequence>
</s:complexType>
<s:complexType name="Employee">
    <s:complexContent>
        <s:extension base="Person">
            <s:sequence>
                <s:element name="EmployeeID" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>

4 つのクラスすべて (Example2APatientPerson、および Employee) が表示されていますが、選択リストには Person クラスは含まれていないことに注意してください。また、PersonPatient、および Employee タイプは既定の場合と同様に定義されていることにも注意してください。

XMLINCLUDEINGROUP=0 を含む選択リストの例

クラス Person の別のサブクラスを追加し、XMLINCLUDEINGROUP を 0 に設定してそのサブクラスを制限するとします。

Class UsingSubclasses.Other Extends UsingSubclasses.Person
{
Parameter XMLINCLUDEINGROUP = 0;
}

この場合、このクラスは選択リストにもスキーマにも含まれません。

サブタイプの置換グループの作成

XML スキーマの仕様では、置換グループの定義も許可されています。置換グループは、選択肢を作成するための代替の方法となります。構文は多少異なります。タイプの明示的な集中リストを作成するのではなく、以下のように、置換対象として考えられるものに注釈を付けます。

<s:complexType name="Example3">
    <s:sequence>
        <s:element ref="Person" minOccurs="0" />
    </s:sequence>
</s:complexType>
<s:element name="Person" type="Person"/>
<s:element name="Employee" type="Employee" substitutionGroup="Person"/>
<s:complexType name="Employee">
    <s:complexContent>
        <s:extension base="Person">
            <s:sequence>
                <s:element name="EmployeeID" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>
<s:complexType name="Person">
    <s:sequence>
        <s:element name="Name" type="s:string" />
        <s:element name="DOB" type="s:date" />
    </s:sequence>
</s:complexType>
<s:element name="Patient" type="Patient" substitutionGroup="Person"/>
<s:complexType name="Patient">
    <s:complexContent>
        <s:extension base="Person">
            <s:sequence>
                <s:element name="PatientID" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>

このスキーマを作成するには、以下のクラスを使用します。

Class UsingSubclasses.Example3 Extends (%Persistent, %XML.Adaptor)
{
Property Person As UsingSubclasses.Person
(XMLTYPECONSTRAINT = "SUBSTITUTIONGROUP");
}

置換グループでのサブクラスの制限

任意のプロパティで、XMLTYPECONSTRAINT プロパティ・パラメータを <SUBSTITUTIONGROUP> に設定すると、前述の例のように、グループはそのプロパティのタイプのすべてのサブクラスで自動的に構成されます。XMLINCLUDEINGROUP パラメータを使用して、置換グループに含めないように、任意のサブクラスにマークを付けます。例えば、Person クラスの別のサブクラスを追加するとします。

Class UsingSubclasses.Other Extends UsingSubclasses.Person
{

Parameter XMLINCLUDEINGROUP = 0;

Property OtherID As %String [ Required ];
}

この場合、このクラスは置換グループに含まれません。そして、このクラスはこの方法で明示的にマークを付けるので、スキーマには含まれません。

スーパークラスをタイプとして表示する方法

XML スキーマで特定のタイプの階層を表示する必要がある場合、Caché クラス階層がプロジェクションでどう解釈されるかを理解する必要があります。

クラス階層はとりわけ、意味をなすデータ構成を表します。この階層は、対応する XML タイプ定義に可能な限り反映されます。

例えば、以下のクラスがあるとします。

  • Base という名前のクラス。3 つのパブリック・プロパティ (Property1Property2、および Property3) を定義します。

  • Addition1 という名前のクラス。Base を拡張し、追加のパブリック・プロパティ (Addition1) を定義します。

  • Addition2 という名前のクラス。Addition1 を拡張し、追加のパブリック・プロパティ (Addition2) を定義します。

Addition2 のスキーマには、何が含まれるでしょうか。5 つのプロパティをすべて表示する必要があります。また、これらのクラスはすべてユーザに定義されたものなので、Addition2 のスキーマは、クラス階層の詳細を示す必要があります。一方、Base が Caché クラス・ライブラリのクラスを拡張し、そのライブラリの別のクラスを拡張する場合、それらの詳細はさほど重要ではありません。

同様に、Addition2 の XML スキーマは、既定では以下のようになります。

<s:complexType name="Addition2">
    <s:complexContent>
        <s:extension base="Addition1">
            <s:sequence>
                <s:element name="Addition2" type="s:decimal" minOccurs="0" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>
<s:complexType name="Addition1">
    <s:complexContent>
        <s:extension base="Base">
            <s:sequence>
                <s:element name="Addition1" type="s:string" minOccurs="0" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>
<s:complexType name="Base">
    <s:sequence>
        <s:element name="Property1" type="s:string" minOccurs="0" />
        <s:element name="Property2" type="s:decimal" minOccurs="0" />
        <s:element name="Property3" type="s:date" minOccurs="0" />
    </s:sequence>
</s:complexType>

XML タイプ定義は複数の継承をサポートしないため、Caché XML サポートでは、一定の簡素化された想定が行われます。複数のスーパークラスを拡張するクラスの場合、そのクラスのタイプは最初にリストに挙げられたスーパークラスであると想定されます。例は以下のようになります。以下の 3 つのクラス定義を考えてみます。AddressPart1 にはプロパティが 1 つ含まれます。

Class GXML.Writer.ShowMultiple.AddressPart1 Extends %XML.Adaptor
{
Property Street As %String [ Required ];
}

AddressPart2 クラスには別のプロパティが含まれます。

Class GXML.Writer.ShowMultiple.AddressPart2 Extends %XML.Adaptor
{
Property City As %String [ Required ];
}

最後に、Address はこれらのクラスの両方から (AddressPart1 を最初のスーパークラスとして) 継承され、さらに多くのプロパティを追加します。

Class GXML.Writer.ShowMultiple.Address Extends 
(GXML.Writers.ShowMultiple.AddressPart1, 
GXML.Writers.ShowMultiple.AddressPart2)
{
Property State As %String(MAXLEN = 2, PATTERN = "2u") [ Required ];
Property Zip As %String(MAXLEN = 10, PATTERN = "5n.1(1""-""4n)") [ Required ];
}

Address の XML スキーマは以下のようになります。

<s:complexType name="Address">
    <s:complexContent>
        <s:extension base="AddressPart1">
            <s:sequence>
                <s:element name="City" type="s:string" />
                <s:element name="State" type="s:string" />
                <s:element name="Zip" type="s:string" />
            </s:sequence>
        </s:extension>
    </s:complexContent>
</s:complexType>
<s:complexType name="AddressPart1">
    <s:sequence>
        <s:element name="Street" type="s:string" />
    </s:sequence>
</s:complexType>

これから以下の点がわかります。

  • 最初にリストに挙げられたスーパークラス、AddressPart1 は、対応する XML タイプによって表されます。この XML タイプには、予期される詳細がすべて含まれます。

  • AddressPart1 タイプに含まれるプロパティ以外にも、残りのプロパティすべてが Address タイプに割り当てられます。これは、AddressPart1 クラスのマッピング後、これらのプロパティの表現として唯一考えられるものです。

  • AddressPart1 および AddressPart2 はどちらも %XML.AdaptorOpens in a new tab のサブクラスですが、%XML.AdaptorOpens in a new tab クラスの構成は公開されません。重視されるのはカスタム・クラスです。

以下の規則は、任意のクラスのスキーマを表示する際のスーパークラスの処理方法を制御します。

  • スーパークラスが %XML.AdaptorOpens in a new tab から継承される場合、このクラスの投影されたプロパティをすべて表す XML タイプによって表されます。短いクラス名がそのプロパティの XML タイプ名として使用されます。クラスで XMLTYPE パラメータの値が指定されている場合、代わりにその値がタイプ名として使用されます。

  • スーパークラスが %XML.AdaptorOpens in a new tab から継承されない場合、XML タイプには表されません。プロパティがある場合、そのプロパティは継承するクラス (表示しているスキーマのクラス) に割り当てられます。

  • 任意のクラスが複数のスーパークラスから継承される場合、最初のスーパークラスに対して XML タイプが作成されます (該当する場合。前述の規則を参照)。最初のスーパークラスに属さないプロパティはすべて、前述の例のように、継承するクラスに割り当てられます。

複数の XML 対応スーパークラスに基づいたクラス

場合によっては、1 つの特定のクラスが複数の XML 対応スーパークラスに基づいていることがあります。そのような場合、対応する XML スキーマは、これらのクラスがリストされる順序であると見なします。例えば、以下に示すクラスについて考えてみます。このクラスは 2 つの XML 対応スーパークラスを継承しています。

Class Test.Default Extends (Test.Superclass1, Test.Superclass2)
{
///additional class members ...
}

このクラスの XML スキーマは、左端のクラス Test.Superclass1 から派生した XML タイプを先にリストし、Test.Superclass2 から派生した XML リストは後にリストします。このクラスに含まれるオブジェクトの XML 出力を生成するときも、この順序と同じになります。

XML スキーマ (および出力) が右から左の順序で決定されるようにするには、XMLINHERITANCE パラメータを "right" に設定します。例えば、以下のようになります。

Class Test.Default Extends (Test.Superclass1, Test.Superclass2)
{
Parameter XMLINHERITANCE = "right";

///additional class members ...
}
FeedbackOpens in a new tab