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?

Caché オブジェクトからの XML 出力の記述

この章では、Caché オブジェクトから XML 出力を生成する方法について説明します。以下のトピックについて説明します。

XML ドキュメントの DOM 表現” の章の “DOM からの XML 出力の記述” も参照してください。

XML ライターの作成の概要

Caché には、Caché オブジェクトの XML 出力を生成するツールが用意されています。"オブジェクトの XML への投影" の説明に従って、XML プロジェクションの詳細を指定します。次に、目的の XML 出力の全体構造を指定するライター・メソッドを作成します。この全体構造では、文字のエンコード、オブジェクトの記述順序、処理命令も対象とするかどうかなどを指定します。

基本的な要件は以下のとおりです。

次のターミナル・セッションは、XML 対応オブジェクトにアクセスして出力を生成する簡単な例を示しています。

GXML>Set p=##class(GXML.Person).%OpenId(1)
 
GXML>Set w=##class(%XML.Writer).%New()
 
GXML>Set w.Indent=1
 
GXML>Set status=w.RootObject(p)
<?xml version="1.0" encoding="UTF-8"?>
<Person GroupID="R9685">
  <Name>Zimmerman,Jeff R.</Name>
  <DOB>1961-10-03</DOB>
  <Address>
    <City>Islip</City>
    <Zip>15020</Zip>
  </Address>
  <Doctors>
    <Doctor>
      <Name>Sorenson,Chad A.</Name>
    </Doctor>
    <Doctor>
      <Name>Sorenson,Chad A.</Name>
    </Doctor>
    <Doctor>
      <Name>Uberoth,Roger C.</Name>
    </Doctor>
  </Doctors>
</Person>

以下のセクションで詳細を説明します。

出力メソッドの作成

作成する出力メソッドでは、XML ドキュメントの構成部分を記述する順序を指定します。XML ドキュメント全体を出力するのか、その断片を出力するのかによって、出力メソッドの全体的な構造は異なります。このセクションでは、以下の項目について説明します。

メソッドの全体的な構造

メソッドは、以下の操作の一部またはすべてをこの順序で実行する必要があります。

  1. 無効である可能性のあるオブジェクトを使用する場合は、そのオブジェクトの %ValidateObject() メソッドを呼び出し、返されるステータスをチェックします。オブジェクトが有効ではない場合、XML も有効とはなりません。

    %XML.WriterOpens in a new tab ではエクスポートの前にオブジェクトの検証はしません。これは、オブジェクトの作成完了後にそれが未検証である場合、(例えば、必須プロパティが失われてるために) オブジェクト (XML) が無効となる可能性があることを意味します。

  2. %XML.WriterOpens in a new tab クラスのインスタンスを作成し、オプションでそのプロパティを設定します。

    特に以下のプロパティを設定する必要がある場合があります。

    • Indent — 出力にインデントと行のラッピングを適用するかどうかを制御します。Indent を 1 に設定するとインデントと行のラッピングが適用され、Indent を 0 に設定すると出力は長い単一の行となります。既定値は 0 です。

      後述のサブセクション “インデント・オプションに関する詳細” を参照してください。

    • IndentChars — インデントに使用する文字を指定します。既定では、2 つのスペースで構成される文字列です。Indent を 0 に設定すると、このプロパティには何の効果もなくなります。

    • Charset — 使用する文字セットを指定します。“出力の文字セットの指定” を参照してください。

    ドキュメントを読みやすくするために、ここで挙げる例では Indent を 1 に設定します。

    また、この章で後述の “プロローグに影響するプロパティ” および “ライターのその他のプロパティ” のセクションも参照してください。

  3. 出力先を指定します。

    既定では、現在のデバイスに出力されます。出力先を指定するには、ドキュメントの出力を開始する前に、以下のメソッドのいずれかを呼び出します。

    • OutputToDevice() — 出力先を現在のデバイスに設定します。

    • OutputToFile() — 出力先を指定されたファイルに設定します。パスの指定は、絶対パスでも相対パスでもかまいません。存在するディレクトリ・パスを指定するようにします。

    • OutputToString() — 出力先を文字列に設定します。その後で、他のメソッドを使用してこの文字列を取得できます。

    • OutputToStream() — 出力先を指定されたストリームに設定します。

  4. ドキュメントを開始します。これには StartDocument() メソッドを使用できます。StartDocument() でドキュメントを開始していない場合は、Write()WriteDocType()RootElement()WriteComment()、および WriteProcessingInstruction() の各メソッドを使用すると、暗黙的にドキュメントを開始できます。

  5. 必要に応じて、ドキュメントのプロローグの行を記述します。使用できるメソッドは以下のとおりです。

  6. 必要に応じて、既定のネームスペースを指定します。XML ネームスペースが定義されていないクラスにはこれが使用されます。“既定のネームスペースの指定” を参照してください。

  7. 必要に応じて、ルート要素にネームスペース宣言を追加します。このためには、ルート要素を開始するにいくつかのユーティリティ・メソッドを呼び出すことができます。“ネームスペース宣言の追加” を参照してください。

  8. ドキュメントのルート要素の記述を開始します。その詳細は、そのルート要素を Caché オブジェクトに対応させるかどうかで異なります。以下の 2 つの可能性があります。

    • ルート要素は Caché オブジェクトに直接対応している可能性があります。多くの場合、これに該当するのは、ある 1 つのオブジェクトのみの出力を生成する場合です。

      この場合は、RootObject() メソッドを使用し、指定の XML 対応オブジェクトをルート要素として記述します。

    • ルート要素を他の要素セットの単なるラッパとし、これらの要素を Caché オブジェクトとすることも可能です。

      この場合は、RootElement() メソッドを使用して、指定した名前を持つルートレベル要素を挿入します。

    また、“ルート要素の記述” も参照してください。

  9. RootElement() メソッドを使用した場合は、1 つ以上の要素の出力をルート要素の中に生成するメソッドを呼び出します。ルート要素の中には、自由な順序と論理であらゆる要素を記述できます。個々の要素を記述する方法にはいくつか種類があり、これらを組み合わせることもできます。

    • Object() メソッドを使用して、XML 対応オブジェクトを記述できます。この要素の名前を指定します。または、オブジェクトで定義されている既定の名前を使用することもできます。

    • Element() メソッドを使用すると、要素の開始タグを指定した名前で記述できます。それに続いて、WriteAttribute()WriteChars()WriteCData()、およびその他のメソッドを使用して、要素のコンテンツ、属性、子要素を記述できます。この子要素には、他の Element() または Object() を使用できます。要素の終了を示すには、EndElement() メソッドを使用します。

    • %XML.ElementOpens in a new tab クラスを使用して、要素を手動で構築できます。

    詳細は、“要素の手動作成” を参照してください。

  10. RootElement() メソッドを使用した場合、EndRootElement() メソッドを呼び出します。このメソッドを使用すると、ドキュメントのルート要素が閉じ、インデントを使用している場合は、ドキュメントの構成に応じてインデントが減少します。

  11. StartDocument() メソッドを使用して開始したドキュメントでは、EndDocument() メソッドを呼び出してドキュメントを閉じます。

  12. 出力先を文字列とした場合は、GetXMLString() メソッドを使用するとその文字列を取得できます。

この他にも作成方法は考えられますが、特定の状況でなければ呼び出せないメソッドがある点は注意を要します。具体的には、あるドキュメントの記述を開始すると、そのドキュメントを終了しない限り、他のドキュメントを開始できません。ドキュメントを開始したまま、他のドキュメントを開始しようとすると、ライター・メソッドから次のステータスが返されます。

#6275: Cannot output a new XML document or change %XML.Writer properties 
until the current document is completed.

StartDocument() メソッドは、ドキュメントを明示的に開始します。前述のように、Write()WriteDocType()RootElement()WriteComment()、および WriteProcessingInstruction() など、他のメソッドはドキュメントを暗黙的に開始します。

Note:

ここで説明したメソッドは、具体的な構成単位を XML ドキュメントに記述できるように設計されていますが、ドキュメントに対するさらに高度な制御が必要なこともあります。%XML.WriterOpens in a new tab クラスには別のメソッドとして Write() があります。このメソッドを使用すると、出力の中のどの位置にでも任意の文字列を記述できます。

また、Reset() メソッドを使用して、ライター・プロパティおよび出力メソッドを再初期化できます。これは、XML ドキュメントを生成し、ライター・インスタンスを新しく作成せずに別の XML ドキュメントを生成しようとする場合に役立ちます。

エラーのチェック

%XML.WriterOpens in a new tab のメソッドのほとんどはステータスを返します。メソッドを実行するたびに返されるステータスを確認し、必要に応じて実行を中止します。

コメント行の挿入

前述のように、コメント行を挿入するには WriteComment() メソッドを使用します。このメソッドは、ドキュメント内の任意の場所で使用できます。XML ドキュメントの記述を開始していない場合は、このメソッドを実行すると暗黙的にドキュメントが開始されます。

例 1

以下の例のメソッドは、指定された XML 対応オブジェクトの XML 出力を生成します。

ClassMethod Write(obj) As %Status
{
    set writer=##class(%XML.Writer).%New()
    set writer.Indent=1

    //these steps are not really needed because 
    //this is the default destination
    set status=writer.OutputToDevice()
    if $$$ISERR(status) {
        do $System.Status.DisplayError(status) 
        quit $$$ERROR($$$GeneralError, "Output destination not valid")
    }

    set status=writer.RootObject(obj)
    if $$$ISERR(status) {
        do $System.Status.DisplayError(status) 
        quit $$$ERROR($$$GeneralError, "Error writing root object")
    }
        
    quit status
}

このメソッドは OutputToDevice() メソッドを使用して、出力を既定の出力先である現在のデバイスに転送することに注意してください。これは必ずしも必要ではありませんが、デモンストレーション用に示します。

このメソッドを以下のように実行するとします。

 set obj=##class(GXML.Person4).%OpenId(1)
 do ##class(MyWriters.BasicWriter).Write(obj)

出力は当然、使用されるクラスに依存しますが、以下のようになる場合があります。

<?xml version="1.0" encoding="UTF-8"?>
<Person4>
  <Name>Tesla,Alexandra L.</Name>
  <DOB>1983-11-16</DOB>
  <GroupID>Y9910</GroupID>
  <Address>
    <City>Albany</City>
    <Zip>24450</Zip>
  </Address>
  <Doctors>
    <Doc>
      <Name>Schulte,Frances T.</Name>
    </Doc>
    <Doc>
      <Name>Smith,Albert M.</Name>
    </Doc>
  </Doctors>
</Person4>

例 2

以下の例のメソッドは、指定された XML 対応クラスの、ランダムに選ばれた単一の保存済みオブジェクトの XML 出力を生成します。まず、次に示すユーティリティ・メソッドを使用します。

Class Utils.Utils
{

/// method to go through extent for the given class & return all the IDs
ClassMethod GetList(cls) As %Collection.ListOfDT [ SqlProc ]
{
    set extent=cls_":Extent"
    set returnlist=##class(%Collection.ListOfDT).%New()
    set resultSet=##class(%ResultSet).%New(extent)
    set status=resultSet.Execute()
    while (resultSet.Next() '=0)
    {
        set tempid=resultSet.Get("ID")
        do returnlist.Insert(tempid)
    }
    do resultSet.Close()
    quit returnlist
}
}

このメソッドは、指定されたクラスの現在のエクステントからすべての ID を取得し、それをリストに返します。

ライター・メソッドは以下のとおりです。

ClassMethod WriteOneToDevice(cls) As %Status
{
    set writer=##class(%XML.Writer).%New()
    set writer.Indent=1

    set status=writer.OutputToDevice()
    if $$$ISERR(status) {
        do $System.Status.DisplayError(status) 
        quit $$$ERROR($$$GeneralError, "Output destination not valid")
    }

    set IDlist=##class(Utils.Utils).GetList(cls)
    set rand=$random(IDlist.Count())+1
    set objid=IDlist.GetAt(rand)
    set obj=$CLASSMETHOD(cls,"%OpenId",objid)

    set status=writer.RootObject(obj)
    if $$$ISERR(status) {
        do $System.Status.DisplayError(status) 
        quit $$$ERROR($$$GeneralError,"Error writing root object")}
        
    quit status
}

この例は、クラスを XML 対応にする効果を確認するのみで、表示するオブジェクトは問わないときに便利です。

インデント・オプションに関する詳細

既述のとおり、ライターの Indent プロパティを使用して、出力結果に追加の改行が含まれるようにして、より読みやすいものにすることができます。このフォーマットに対する正式な仕様はありません。ここでは、Indent が 1 に等しい場合に %XML.WriterOpens in a new tab によって使用されるルールについて説明します。

  • 空白文字のみを含む要素があれば、空の要素に変換されます。

  • 各要素は、別々の行に配置されます。

  • ある要素が、先行する要素の子である場合には、その要素は親要素を基準にしてインデントされます。このインデント設定は、2 つのスペースを既定値とする IndentChars プロパティによって決定されます。

出力の文字セットの指定

出力ドキュメントに使用する文字セットを指定するために、ライター・インスタンスの Charset プロパティを設定できます。"UTF-8" または "UTF-16" および Caché でサポートされるその他の文字セットを指定できます。

既定のエンコードの詳細は、このドキュメント内の前述の “入出力の文字エンコード” を参照してください。

プロローグの記述

XML ファイルのプロローグ (ルート要素の前のセクション) には、ドキュメント・タイプの定義、処理命令、およびコメントを含めることができます。このセクションでは、以下の項目について説明します。

プロローグに影響するプロパティ

ライター・インスタンスで、以下のプロパティがプロローグに影響します。

Charset

XML 宣言の文字セット宣言、および (それに対応して) 出力に使用する文字セットのエンコードを制御します。“出力の文字セットの指定” を参照してください。

NoXmlDeclaration

出力に XML 宣言を記述するかどうかを制御します。ほとんどの場合、既定値は 0 で、XML 宣言が記述されます。文字セットを指定していない場合に文字列または文字ストリームを出力先に指定すると、既定値は 1 で、宣言は記述されません。

ドキュメント・タイプの定義の生成

ルート要素の前にドキュメント・タイプの定義を記述して、ドキュメントで使用するスキーマを定義できます。ドキュメント・タイプの定義を生成するには、WriteDocType() メソッドを使用します。このメソッドには、必須の引数が 1 つ、オプションの引数が 3 つあります。このドキュメントで目的とする範囲では、ドキュメント・タイプの定義に記述する内容として以下のものが考えられます。

<!DOCTYPE doc_type_name external_subset [internal_subset]>

ここに示すように、ドキュメント・タイプには名前があり、その名前は、XML の規則に従ってルート要素の名前にする必要があります。この定義では、外部サブセットまたは内部サブセット、あるいはその両方を指定できます。

external_subset セクションは、他の場所にある DTD ファイルを指定します。このセクションの構造は以下のいずれかです。

PUBLIC public_literal_identifier
PUBLIC public_literal_identifier system_literal_identifier
SYSTEM system_literal_identifier

ここでは、public_literal_identifier および system_literal_identifier は DTD の URI を指定する文字列です。DTD では、パブリック識別子とシステム識別子の両方を指定できます。以下は、パブリック識別子とシステム識別子の両方を使用した外部サブセットを持つドキュメント・タイプの定義の例です。

<!DOCTYPE hatches <!ENTITY open-hatch
         PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
         "http://www.textuality.com/boilerplate/OpenHatch.xml">>

internal_subset セクションはエンティティ定義のセットです。以下は、定義の内部セットのみを持つドキュメント・タイプの定義の例です。

<!DOCTYPE teams [ <!ENTITY baseball team (name,city,player*)>
                   !ENTITY name (#PCDATA)>
                   !ENTITY city (#PCDATA)>
                   !ENTITY player (#PCDATA)>
  ] >

WriteDocType() メソッドは以下の 4 つの引数をとります。

  • 最初の引数は、XML ドキュメントの中で使用できるように、ドキュメント・タイプの名前を指定します。この引数は必須で、有効な XML 識別子を指定する必要があります。また、このドキュメント内のルート・レベル要素の名前として、これと同じ名前を使用する必要があります。

  • 2 番目と 3 番目の引数はオプションで、以下のように定義の外部部分を指定します。

    WriteDocType の引数
    2 番目の引数 3 番目の引数 結果として得られる外部部分
    publicURI null PUBLIC “publicURI
    publicURI systemURI PUBLIC “publicURI” “systemURI
    null systemURI SYSTEM “systemURI
  • 4 番目の引数もオプションで、定義の内部部分を指定します。この引数に null 以外の値を指定すると、その値は角括弧 ([]) で囲まれ、定義末尾の適切な場所に置かれます。これ以外の文字は追加されません。

処理命令の記述

XML に処理命令を記述するには、WriteProcessingInstruction() メソッドを使用します。このメソッドは以下の 2 つの引数をとります。

  1. 処理命令の名前 (ターゲット)

  2. 文字列で記述した処理命令

このメソッドを使用すると、以下のような内容が XML に記述されます。

<?name instructions?>

例えば、以下の処理命令を記述するとします。

<?xml-stylesheet type="text/css" href="mystyles.css"?>

これは、以下のように WriteProcessingInstruction() メソッドを呼び出すことで実現できます。

 set instructions="type=""text/css"" href=""mystyles.css"""
 set status=writer.WriteProcessingInstruction("xml-stylesheet", instructions)

既定のネームスペースの指定

ライター・インスタンスでは、既定のネームスペースを指定できます。既定のネームスペースは、NAMESPACE パラメータが設定されていないクラスにのみ適用されます。選択肢はいくつかあります。

  • 既定のネームスペースを、出力メソッド内に指定できます。4 つの主な出力メソッド (RootObject()RootElement()Object()、または Element()) すべてがネームスペースを引数として受け入れます。NAMESPACE パラメータがクラス定義で設定されない場合のみ、該当する要素がネームスペースに割り当てられます。

  • ライター・インスタンスの全体の既定ネームスペースを指定できます。そのためには、ライター・インスタンスの DefaultNamespace プロパティの値を指定します。

以下のクラスを考えてみます。

Class Writers.BasicDemoPerson Extends (%RegisteredObject, %XML.Adaptor)
{

Parameter XMLNAME="Person";

Property Name As %Name;

Property DOB As %Date;

}

既定では、このクラスのオブジェクトを単純にエクスポートする場合は、出力は以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<Person>
  <Name>Persephone MacMillan</Name>
  <DOB>1976-02-20</DOB>
</Person>

対照的に、DefaultNamespace をライター・インスタンスの "http://www.person.org" に設定してオブジェクトをエクスポートする場合は、出力は以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<Person xmlns="www.person.org">
  <Name>Persephone MacMillan</Name>
  <DOB>1976-02-20</DOB>
</Person>

この場合、既定のネームスペースが <Person> 要素で使用されます。この要素は、それ以外ではネームスペースに割り当てられません。

ネームスペース宣言の追加

既定の動作

%XML.WriterOpens in a new tab クラスは自動的にネームスペース宣言を挿入し、ネームスペース接頭語を生成し、その接頭語を適切な場所に適用します。例えば、以下のクラス定義について考えてみます。

Class ResearchWriters.PersonNS Extends (%Persistent, %XML.Adaptor)
{

Parameter NAMESPACE = "http://www.person.com";

Parameter XMLNAME = "Person";

Property Name As %Name;

Property DOB As %Date;

}

このクラスのオブジェクトを複数エクスポートする場合は、以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <Person xmlns="http://www.person.com">
    <Name>Persephone MacMillan</Name>
    <DOB>1975-09-15</DOB>
  </Person>
  <Person xmlns="http://www.person.com">
    <Name>Joseph White</Name>
    <DOB>2003-01-31</DOB>
  </Person>
...

ネームスペース宣言は、各 <Person> 要素に自動的に追加されます。ドキュメントのルートにのみ追加する方が好ましいと思われるかもしれません。

宣言の手動追加

XML 出力にネームスペースを導入するタイミングを制御できます。次のメソッドはすべて、その直後に記述される要素に影響を及ぼします。ただし、その要素の後に記述される要素には影響しません。使用上の便宜のために、いくつかのメソッドでは標準の W3 ネームスペースを追加します。

一般的には、これらのメソッドを使用してネームスペース宣言をドキュメントのルート要素に追加します。つまり、RootObject() または RootElement() を呼び出す前に、これらのメソッドを 1 つ以上呼び出します。

Note:

これらのメソッドはいずれも、ネームスペースに要素を割り当てず、これらのネームスペースが既定のネームスペースとして追加されることはありません。特定の要素を生成する際、“ルート要素の記述” および “XML 要素の生成” で後述するように、使用するネームスペースを示します。

AddNamespace()
method AddNamespace(namespace As %String, 
                    prefix As %String, 
                    schemaLocation As %String) as %Status

指定のネームスペースを追加します。ここで、namespace は追加するネームスペース、prefix はこのネームスペースのオプションの接頭語、schemaLocation は対応するスキーマの場所を示すオプションの URI です。

接頭語を指定しない場合、接頭語が自動的に生成されます (s01s02 などの形式)。

以下の例は、このメソッドの効果を示しています。まず、Person クラスが (NAMESPACEOpens in a new tab クラス・パラメータを使用して) ネームスペースに割り当てられているとします。先に AddNamespace() メソッドを呼び出さずにこのクラスのインスタンスの出力を生成すると、以下のような結果が得られます。

<?xml version="1.0" encoding="UTF-8"?>
<Root>
  <Person xmlns="http://www.person.org">
    <Name>Love,Bart Y.</Name>
...

別の方法として、ルート要素を記述する前に、以下のように AddNamespace() メソッドを呼び出すとします。

 set status=writer.AddNamespace("http:///www.person.org","p")

その後でルート要素を生成すると、以下の結果が得られます。

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:p="http:///www.person.org">
  <Person xmlns="http://www.person.org">
...

または次のように、関連付けられたスキーマの場所を示す 3 番目の引数を指定して AddNamespace() メソッドを呼び出します。

 set status=writer.AddNamespace("http:///www.person.org","p","http://www.MyCompany.com/schemas/person.xsd")

その後で Root 要素を生成すると、以下の結果が得られます。

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:p="http:///www.person.org" 
xsi:schemaLocation="http:///www.person.org http://www.MyCompany.com/schemas/person.xsd" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Person xmlns="http://www.person.org">
...

AddInstanceNamespace()
method AddInstanceNamespace(prefix As %String) as %Status

W3 スキーマのインスタンスのネームスペースを追加します。prefix はこのネームスペースで使用するオプションの接頭語です。既定の接頭語は xsi です。

以下はその例です。

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
AddSchemaNamespace()
method AddSchemaNamespace(prefix As %String) as %Status

W3 スキーマのネームスペースを追加します。prefix はこのネームスペースで使用するオプションの接頭語です。既定の接頭語は s です。

以下はその例です。

<Root xmlns:s="http://www.w3.org/2001/XMLSchema">
...
AddSOAPNamespace()
method AddSOAPNamespace(soapPrefix As %String, 
                        schemaPrefix As %String, 
                        xsiPrefix As %String) as %Status

W3 SOAP エンコードのネームスペース、SOAP スキーマのネームスペース、および SOAP スキーマのインスタンスのネームスペースを追加します。このメソッドは、各ネームスペースの接頭語を示すオプションの引数を 1 つずつ、計 3 つの引数をとります。各ネームスペースの既定の引数は、それぞれ SOAP-ENCs、および xsi です。

以下はその例です。

<Root xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:s="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...

この章で後述する “SOAP でエンコードされた XMLの生成” も参照してください。

AddSOAP12Namespace()
method AddSOAP12Namespace(soapPrefix As %String, 
                          schemaPrefix As %String, 
                          xsiPrefix As %String) as %Status

W3 SOAP 1.2 エンコードのネームスペース、SOAP スキーマのネームスペース、および SOAP スキーマのインスタンスのネームスペースを追加します。

以下はその例です。

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" 
xmlns:s="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...

これらのメソッドを 1 つ以上使用できます。複数のメソッドを使用すると、それによって影響される要素には、指定したすべてのネームスペースの宣言が記述されます。

使用例は、“クラスからの XML スキーマの生成” の章の “より複雑なスキーマの例” を参照してください。

ルート要素の記述

XML ドキュメントにはルート要素を 1 つのみ記述する必要があります。この要素を作成するには、以下の 2 つの方法があります。

  • ルート要素は Caché の 1 つの XML 対応オブジェクトに直接対応している可能性があります。

    この場合は、RootObject() メソッドを使用し、指定の XML 対応オブジェクトをルート要素として記述します。出力には、そのオブジェクトのすべてのオブジェクト参照が記述されます。ルート要素にはそのオブジェクトの構造が取り込まれ、そこに追加の要素を挿入することはできません。この要素の名前を指定することも、XML 対応オブジェクトで定義されている既定の名前を使用することもできます。

    前述の例では、この方法を使用しました。

  • ルート要素を他の要素セット (おそらく XML 対応のオブジェクトのセット) の単なるラッパとすることも可能です。

    この場合は、RootElement() メソッドを使用して、指定した名前を持つルートレベル要素を挿入します。インデントされているドキュメントでこのメソッドを使用すると、これに続く操作でインデント・レベルが上がります。

    次に、1 つ以上の要素の出力をルート要素の中に生成する別のメソッドを呼び出します。ルートの中では、任意の順序または論理で必要な要素を追加できます。詳細は、“要素の手動作成” を参照してください。この後、EndRootElement() メソッドを呼び出してルート要素を閉じます。

    使用例は、次のセクションを参照してください。

どちらの場合でも、ルート要素に使用するネームスペースを指定できます。これは、XML 対応クラスに NAMESPACE パラメータの値がない場合にのみ適用されます。“ネームスペースの割り当ての概要” を参照してください。

ドキュメントにドキュメント・タイプの定義が含まれる場合、その DTD の名前はルート要素の名前と同じにする必要があることに注意してください。

XML 要素の生成

RootElement() を使用してドキュメントのルート要素を開始した場合、そのルート要素の中で各要素を生成する作業はユーザ側で実行する必要があります。これには以下の 3 つの方法があります。

エクスポートされたオブジェクトのネームスペースへの割り当ての詳細は、この章で後述する “ネームスペース使用の制御” を参照してください。

要素としてのオブジェクトの生成

Caché オブジェクトから要素として出力を生成できます。この場合は、Object() メソッドを使用して XML 対応オブジェクトを記述します。出力には、そのオブジェクトのすべてのオブジェクト参照が記述されます。この要素の名前を指定します。または、オブジェクトで定義されている既定の名前を使用することもできます。

Object() メソッドは、RootElement() メソッドを実行してから EndRootElement() メソッドを実行するまでの間でのみ使用できます。

この例では、指定された XML 対応クラスのすべての保存済みインスタンスの出力を生成します。

ClassMethod WriteAll(cls As %String, directory As %String = "c:\")
{
    //check that cls extends %XML.Adaptor
    Set check=1
    Try {
       Set check=$classmethod(cls,"%Extends","%XML.Adaptor")
       } Catch {
           Set check=0
           }

    If (check'=1) {
        Write "Class does not extend %XML.Adaptor or is not compiled"
        Quit 
        }
        
    Set filename=directory_cls_".xml"
        
    Set writer=##class(%XML.Writer).%New()
    Set writer.Indent=1
    Set status=writer.OutputToFile(filename)
    if $$$ISERR(status) { do $System.Status.DisplayError(status) quit  }
    
    Set status=writer.RootElement("SampleOutput")
    if $$$ISERR(status) { do $System.Status.DisplayError(status) quit  }

    //Get IDs of objects in the extent for the given class
    Set rset = ##class(%ResultSet).%New(cls_":Extent")
    Set status=rset.Execute()
    if $$$ISERR(status) { do $System.Status.DisplayError(status) quit  }

    While (rset.Next()) {
        //for each ID, write that object
        Set objid=rset.Data("ID")
        Set obj=$CLASSMETHOD(cls,"%OpenId",objid)
        Set status=writer.Object(obj)
        If $$$ISERR(status) {Do $System.Status.DisplayError(status) Quit}}
        
    Do writer.EndRootElement()
    Do writer.EndDocument()
}

このメソッドを実行して得られる出力には、指定されたクラスのすべての保存済みオブジェクトが、ルート要素の中で入れ子になった形式で記述されています。Sample.PersonOpens in a new tab については、出力は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<SampleOutput>
  <Person>
    <Name>Tillem,Robert Y.</Name>
    <SSN>967-54-9687</SSN>
    <DOB>1961-11-27</DOB>
    <Home>
      <Street>3355 First Court</Street>
      <City>Reston</City>
      <State>WY</State>
      <Zip>11090</Zip>
    </Home>
    <Office>
      <Street>4922 Main Drive</Street>
      <City>Newton</City>
      <State>NM</State>
      <Zip>98073</Zip>
    </Office>
    <FavoriteColors>
      <FavoriteColorsItem>Red</FavoriteColorsItem>
    </FavoriteColors>
    <Age>47</Age>
  </Person>
  <Person>
    <Name>Waters,Ed X.</Name>
    <SSN>361-66-2801</SSN>
    <DOB>1957-05-29</DOB>
    <Home>
      <Street>5947 Madison Drive</Street>
...
</SampleOutput>

要素の手動作成

手動で XML 要素を作成できます。この場合は、Element() メソッドを使用して、要素の開始タグを指定した名前で記述します。それに続いて、要素のコンテンツ、属性、子要素を記述できます。要素の終了を示すには、EndElement() メソッドを使用します。

関連するメソッドは以下のとおりです。

Element()
method Element(tag, namespace As %String) as %Status

開始タグを記述します。要素のネームスペースを指定できます。これは、XML 対応クラスに NAMESPACE パラメータの値がない場合にのみ適用されます。“ネームスペースの割り当ての概要” を参照してください。

WriteAttribute()
method WriteAttribute(name As %String, 
                      value As %String  = "", 
                      namespace As %String, 
                      valueNamespace As %String  = "", 
                      global As %Boolean  = 0) as %Status

属性を記述します。属性名と属性値を指定する必要があります。引数 namespace は、属性名のネームスペースです。引数 valueNamespace は、属性値のネームスペースであり、XML スキーマ・ネームスペースで値が定義されるときに使用されます。

属性が、関連付けられている XML スキーマでグローバルであり、接頭語を持つ必要がある場合は、global に対して True を指定します。

このメソッドを使用する場合は、Element() の直後 (または RootElement() の後) に使用する必要があります。

WriteChars()
method WriteChars(text) as %Status

文字列を記述します。要素のコンテンツに適した文字列とするために必要なエスケープ処理も実行します。引数のデータ型は、%StringOpens in a new tab または %CharacterStreamOpens in a new tab とする必要があります。

WriteCData()
method WriteCData(text) as %Status

CDATA セクションを記述します。引数のデータ型は、%StringOpens in a new tab または %CharacterStreamOpens in a new tab とする必要があります。

WriteBase64()
method WriteBase64(binary) as %Status

指定したバイナリ・バイトを Base-64 としてエンコードし、得られたテキストを要素のコンテンツとして記述します。引数のデータ型は、%BinaryOpens in a new tab または %BinaryStreamOpens in a new tab とする必要があります。

WriteBinHex()
method WriteBinHex(binary) as %Status

指定したバイナリ・バイトを BINHEX としてエンコードし、得られたテキストを要素のコンテンツとして記述します。引数のデータ型は、%BinaryOpens in a new tab または %BinaryStreamOpens in a new tab とする必要があります。

EndElement()
method EndElement() as %Status

該当する要素を終了します。

これらのメソッドは、RootElement() メソッドを実行してから EndRootElement() メソッドを実行するまでの間でのみ使用できます。

Note:

ここで説明したメソッドは、具体的で論理的な内容を XML ドキュメントに記述できるように設計されていますが、ドキュメントに対するさらに高度な制御が必要なこともあります。%XML.Writer Opens in a new tab クラスには別のメソッドとして Write() があります。このメソッドを使用すると、任意の文字列を記述できます。ただし、その結果を検証する機能は用意されていないので、得られた結果が適格な XML ドキュメントであることをユーザ側で確認する必要があります。

以下にルーチンの例を示します。

 //write output to current device
 //simple demo of Element & related methods
 
 set writer=##class(%XML.Writer).%New()
 set writer.Indent=1
 
 set status=writer.OutputToDevice()
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.StartDocument()
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.RootElement("root")
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.Element("SampleElement")
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.WriteAttribute("Attribute","12345")
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.Element("subelement")
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.WriteChars("Content")
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.EndElement()
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.Element("subelement")
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.WriteChars("Content")
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.EndElement()
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.EndElement()
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.EndRootElement()
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}
 
 set status=writer.EndDocument()
 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit}

このルーチンの出力は以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <SampleElement Attribute="12345">
    <subelement>Content</subelement>
    <subelement>Content</subelement>
  </SampleElement>
</root>

%XML.Element の使用

前述のセクションでは、Element() を使用して生成する要素を指定しましたが、ネームスペースを指定することもできます。場合によっては、要素名ではなく %XML.ElementOpens in a new tab クラスのインスタンスを使用する必要がある場合があります。このクラスには、以下のプロパティがあります。

  • Local プロパティは、この要素が親要素に対してローカルかどうかを指定し、ネームスペースの制御に影響を与えます。詳細は、後述の “要素が親に対してローカルかどうかの制御” を参照してください。

  • Namespace プロパティは、この要素のネームスペースを指定します。

  • Tagname プロパティは、この要素の名前を指定します。

ここでは、前述の WriteAttribute() メソッドも使用できます。

ネームスペース使用の制御

"オブジェクトの XML への投影" で説明されているように、クラスをネームスペースに割り当てて、対応する XML 要素がそのネームスペースに属するようにすることができます。また、そのクラスのプロパティがそのネームスペースに属するかどうかを制御できます。

そのクラスのオブジェクトを XML にエクスポートすると、%XML.WriterOpens in a new tab クラスには、要素がその親に対してローカルであるかどうかの指定などのオプションが追加されます。このセクションでは、以下のトピックについて説明します。

Note:

Caché XML サポートでは、クラスごとにネームスペースを指定します。一般に、各クラスには独自のネームスペース宣言がありますが、通常は、必要なのは 1 つまたは少数のネームスペースのみです。関連情報も、(グローバルにではなく) クラスごとに指定します。これには、要素が親に対してローカルかどうか、および下位要素が修飾されるかどうかを制御する設定が含まれます。作業を単純化するために、一貫性のある方法を使用することをお勧めします。

ネームスペースの既定の処理

XML 対応クラスをネームスペースに割り当てるには、"オブジェクトの XML への投影" の説明にあるとおり、そのクラスの NAMESPACE パラメータを設定します。%XML.WriterOpens in a new tab クラスは自動的にネームスペース宣言を挿入し、ネームスペース接頭語を生成し、その接頭語を適切な場所に適用します。例えば、以下のクラス定義について考えてみます。

Class GXML.Objects.WithNamespaces.Person Extends (%Persistent, %Populate, %XML.Adaptor)
{
Parameter NAMESPACE = "http://www.person.com";
Property Name As %Name [ Required ];
Property DOB As %Date(FORMAT = 5, MAXVAL = "+$h") [ Required ];
Property GroupID As %Integer(MAXVAL=10,MINVAL=1,XMLPROJECTION="ATTRIBUTE");
}

このクラスのオブジェクトをエクスポートする場合は、以下のようになります。

<Person xmlns="http://www.person.com" GroupID="4">
  <Name>Uberoth,Amanda Q.</Name>
  <DOB>1952-01-13</DOB>
</Person>

以下のことに注意してください。

  • ネームスペース宣言は、各 <Person> 要素に追加されます。

  • <Person> 要素のローカル要素 (<Name> および <DOB>) は、既定では修飾されています。ネームスペースは既定のネームスペースとして追加されるので、これらの要素に追加されます。

  • <Person> 要素の属性 (GroupID) は、既定では修飾されていません。この属性には接頭語がないので、修飾なしと見なされます。

  • ここに示す接頭語は自動的に生成されました (オブジェクトにネームスペースを割り当てる際は、ネームスペースのみを指定し、接頭語は指定しないことに注意してください)。

  • この出力は、ライターでネームスペース関連のプロパティを設定せず、ライターでネームスペース関連のメソッドを使用せずに生成されました。

ネームスペース割り当てのコンテキストの効果

XML 対応オブジェクトが割り当てられるネームスペースは、そのオブジェクトが最上位レベルでエクスポートされるか、または別のオブジェクトのプロパティとしてエクスポートされるかによって異なります。

Address という名前のクラスを考えてみます。NAMESPACE パラメータを使用して、Address クラスに "http://www.address.org" というネームスペースを割り当てるとします。Address クラスのオブジェクトを直接エクスポートした場合、以下のような結果が得られます。

<Address xmlns="http://www.address.org">
  <Street>8280 Main Avenue</Street>
  <City>Washington</City>
  <State>VT</State>
  <Zip>15355</Zip>
</Address>

<Address> 要素とそのすべての要素が同じネームスペース ("http://www.address.org") にあることに注意してください。

一方、Address オブジェクトであるプロパティを持つ Person クラスを考えてみます。また、NAMESPACE パラメータを使用して、Person クラスに "http://www.person.org" というネームスペースを割り当てるとします。Person クラスのオブジェクトをエクスポートした場合、以下のような結果が得られます。

<Person xmlns="http://www.person.org">
  <Name>Zevon,Samantha H.</Name>
  <DOB>1964-05-24</DOB>
  <Address xmlns="http://www.address.org">
     <Street>8280 Main Avenue</Street>
     <City>Washington</City>
     <State>VT</State>
     <Zip>15355</Zip>
  </Address>
</Person>

<Address> 要素が親オブジェクト ("http://www.person.org") のネームスペースにあることに注意してください。ただし、<Address> 要素は "http://www.address.org" のネームスペース内にあります。

ローカル要素が修飾されるかどうかの制御

オブジェクトを最上位レベルでエクスポートすると、そのオブジェクトはグローバル要素として処理されます。そして、そのローカル要素は、XML 対応オブジェクトの ELEMENTQUALIFIED パラメータの設定に応じて処理されます。このクラス・パラメータが設定されていない場合、ライター・プロパティ ElementQualified の値が代わりに使用されます。既定では、これはリテラル形式では 1、エンコード形式では 0 です。

以下の例は、ElementQualified の既定の設定 (1) のオブジェクトを示しています。

<?xml version="1.0" encoding="UTF-8"?>
<PersonNS xmlns="http://www.person.com" GroupID="M9301">
  <Name>Pybus,Gertrude X.</Name>
  <DOB>1986-10-19</DOB>
</PersonNS>

このネームスペースは <PersonNS> 要素に既定のネームスペースとして追加されるため、<Name> および <DOB> 下位要素に適用されます。

ライター定義を変更し、ElementQualified プロパティを 0 に設定したとします。この場合、同じオブジェクトが以下のように表示されます。

<?xml version="1.0" encoding="UTF-8"?>
<s01:PersonNS xmlns:s01="http://www.person.com" GroupID="M9301">
  <Name>Pybus,Gertrude X.</Name>
  <DOB>1986-10-19</DOB>
</s01:PersonNS>

この場合、ネームスペースは <PersonNS> 要素に接頭語を付けて追加されます。これは <PersonNS> 要素では使用されますが、その下位要素では使用されません。

要素が親に対してローカルかどうかの制御

既定では、Object() メソッドを使用して要素を生成し、その要素にネームスペースがある場合、その要素は親に対してローカルではありません。ただし、要素をその親のネームスペースに属するように強制できます。そのためには、Object() メソッドのオプションの local 引数を使用します。これは、4 番目の引数です。

Local 引数 0 の場合 (既定)

ここでは、NAMESPACE クラス・パラメータを "http://www.person.com" に指定する Person クラスについて考えてみます。

ルート要素を開いてから、Object() を使用して Person を生成する場合、<Person> 要素は "http://www.person.com" ネームスペースに入ります。以下の例を考えてみます。

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns="http://www.rootns.org">
   <Person xmlns="http://www.person.com">
      <Name>Adam,George L.</Name>
      <DOB>1947-06-29</DOB>
   </Person>
</Root>

<Person> 要素を他の要素の内部にさらに深く入れ子にすると、同様の結果が得られます。

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns="www.rootns.org">
   <GlobalEl xmlns="globalns">
      <Inner xmlns="innerns">
         <Person xmlns="http://www.person.com">
            <Name>Adam,George L.</Name>
            <DOB>1947-06-29</DOB>
         </Person>
      </Inner>
   </GlobalEl>
</Root>

Local 引数 1 の場合

<Person> 要素をその親に対して強制的にローカルにするには、local 引数を 1 に等しく設定します。そうして前述の出力を再度生成すると、入れ子がより浅い場合、以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns="http://www.rootns.org">
   <s01:Person xmlns="http://www.person.com" 
xmlns:s01="http://www.rootns.org">
      <Name>Adam,George L.</Name>
      <DOB>1947-06-29</DOB>
   </s01:Person>
</Root>

<Person> 要素が現在は、その親要素のネームスペースである "http://www.rootns.org" ネームスペースにあることに注意してください。同様に、入れ子がより深い場合には以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns="www.rootns.org">
   <GlobalEl xmlns="globalns">
      <Inner xmlns="innerns">
         <s01:Person xmlns="http://www.person.com" xmlns:s01="innerns">
            <Name>Adam,George L.</Name>
            <DOB>1947-06-29</DOB>
         </s01:Person>
      </Inner>
   </GlobalEl>
</Root>

属性が修飾されるかどうかの制御

オブジェクトをエクスポートする際、既定では属性は修飾されません。属性を修飾するには、ライター・プロパティ AttributeQualified を 1 に等しく設定します。以下の例は、AttributeQualified が 0 に等しい (または設定されていない) ライターで生成された出力を示しています。

<?xml version="1.0" encoding="UTF-8"?>
<Root>
   <s01:Person xmlns:s01="http://www.person.com" GroupID="E8401">
      <Name>Leiberman,Amanda E.</Name>
      <DOB>1988-10-28</DOB>
   </s01:Person>
</Root>

一方、以下の例は、AttributeQualified が 1 に等しいライターで生成された同じオブジェクトを示しています。

<?xml version="1.0" encoding="UTF-8"?>
<Root>
   <s01:Person xmlns:s01="http://www.person.com" s01:GroupID="E8401">
      <Name>Leiberman,Amanda E.</Name>
      <DOB>1988-10-28</DOB>
   </s01:Person>
</Root>

どちらの場合も、要素は修飾されません。

ネームスペースの割り当ての概要

このセクションでは、XML 出力の任意の要素に対してネームスペースを指定する方法を説明します。

最上位レベル要素

最上位レベルでエクスポートされる Caché クラスに相当する要素の場合、以下の規則が適用されます。

  1. このクラスに NAMESPACE パラメータを指定した場合、要素はそのネームスペースに入ります。

  2. このパラメータを指定していない場合、要素はその要素 (RootObject()RootElement()Object()、または Element()) を生成した出力メソッドで指定されたネームスペースに入ります。

  3. 出力メソッドでネームスペースを指定していない場合、要素はライターの DefaultNamespace プロパティで指定されたネームスペースに入ります。

  4. DefaultNamespace プロパティが NULL の場合、要素はどのネームスペースにも入りません。

下位レベル要素

エクスポートしているクラスの下位要素は、そのクラスの ELEMENTQUALIFIED パラメータの影響を受けます。ELEMENTQUALIFIED が設定されていない場合、ライター・プロパティ ElementQualified の値が代わりに使用されます。既定では、これはリテラル形式では 1、エンコード形式では 0 です。

要素が指定されたクラスに対して修飾される場合、そのクラスの下位要素は以下のようにネームスペースに割り当てられます。

  1. 親オブジェクトNAMESPACE パラメータを指定した場合、下位要素はそのネームスペースに明示的に割り当てられます。

  2. このパラメータを指定していない場合、下位要素はその要素 (RootObject()RootElement()Object()、または Element()) を生成した出力メソッドで指定されたネームスペースに明示的に割り当てられます。

  3. 出力メソッドでネームスペースを指定していない場合、下位要素はライターの DefaultNamespace プロパティで指定されたネームスペースに明示的に割り当てられます。

  4. DefaultNamespace プロパティが NULL の場合、下位要素はどのネームスペースにも明示的に割り当てられません。

ネームスペース割り当ての外観の制御

ネームスペース割り当ての制御に加え、ネームスペース割り当てが XML 出力でどのように表示されるかを制御できます。具体的には、以下を制御できます。

ネームスペースの割り当てを明示的と暗黙的のいずれで行うか

ネームスペースに要素や属性を割り当てる際、XML では、ライター・インスタンスの SuppressXmlns プロパティで制御される 2 つの同等の表現が存在します。

ネームスペース "http://www.person.org" に (前述のように NAMESPACE クラス・パラメータを使用して) 割り当てられている Person という名前のオブジェクトの XML 出力を生成するとします。既定の出力例 (SuppressXmlns が 0 に等しい) は以下のとおりです。

<Person xmlns="http://www.person.com" GroupID="4">
  <Name>Uberoth,Amanda Q.</Name>
  <DOB>1952-01-13</DOB>
</Person>

まったく等しいもう 1 つの形式は、以下のとおりです。これは、1 に設定された SuppressXmlns で生成され、ネームスペースに明示的に割り当てられる各要素が、そのネームスペースの接頭語で確実に表されるようにします。

<s01:Person xmlns:s01="http://www.person.com" GroupID="4">
  <s01:Name>Uberoth,Amanda Q.</s01:Name>
  <s01:DOB>1952-01-13</s01:DOB>
</s01:Person>

このプロパティは、ネームスペースの割り当ての表示方法のみに影響し、ネームスペースの割り当て方法は制御しないことに注意してください。ネームスペースを使用しない場合、このパラメータは何の効果も持ちません。

ネームスペースのカスタム接頭語の指定

オブジェクトの XML 出力を生成する場合、システムは必要に応じてネームスペース接頭語を生成します。最初のネームスペースの接頭語は s01、次は s02、のように付与されます。別の接頭語を指定することもできます。そのためには、XML 対応オブジェクト自体のクラス定義で XMLPREFIX パラメータを設定します。このパラメータには以下の 2 つの効果があります。

  • 指定した接頭語が XML 出力で宣言されるようになります。つまり、不要な場合でも宣言されます。

  • 自動生成の接頭語 (このパラメータを設定しない場合はこれが使用される) でない接頭語が使用されます。

詳細は、"オブジェクトの XML への投影" を参照してください。

空文字列 ("") のエクスポート方法の制御

オブジェクトを XML 対応にする場合、NULL 値および空文字列を XML に投影する方法を指定します ("オブジェクトの XML への投影" を参照)。

その指定方法の 1 つは、XML 対応クラスで XMLIGNORENULL"RUNTIME" (大文字/小文字の区別なし) に設定することです。この場合、%XML.WriterOpens in a new tab を使用して出力を生成するときに、Caché は以下のようにライターの RuntimeIgnoreNull プロパティの値を使用して、プロパティが "" の場合の処理方法を決定します。

  • ライターの RuntimeIgnoreNull プロパティが 0 (既定) の場合、XMLNIL パラメータでプロパティのエクスポート方法を制御します。XMLNIL はクラス・パラメータおよびプロパティ・パラメータですが、プロパティ・パラメータが優先されます。

    • XMLNIL が 0 (既定) の場合、プロパティは投影されません。つまり、XML ドキュメントに格納されません。

    • XMLNIL が 1 の場合、プロパティが要素として使用されていると、そのプロパティは以下のようにエクスポートされます。

      <PropName xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
    • XMLNIL が 1 の場合、プロパティが属性として使用されていると、そのプロパティはエクスポートされません。

  • ライターの RuntimeIgnoreNull プロパティが 1 の場合、プロパティは空要素または空属性としてエクスポートされます (これは、常に空要素または空属性としてエクスポートされる $char(0) 値と同様です)。

ライターの RuntimeIgnoreNull プロパティは、XML 対応クラスで XMLIGNORENULL"RUNTIME" に設定されていない限り影響はありません。

例 : RuntimeIgnoreNull が 0 (既定)

まず、以下のクラスについて考えてみます。

Class EmptyStrings.Export Extends (%Persistent, %XML.Adaptor)
{

Parameter XMLNAME="Test";


Parameter XMLIGNORENULL = "RUNTIME";


///project this one as an element 
///XMLNIL is 0, the default
Property Property1 As %String;


///project this one as an attribute 
///XMLNIL is 0, the default
Property Property2 As %String(XMLPROJECTION = "ATTRIBUTE");


///project this one as an element with XMLNIL=1
Property Property3 As %String(XMLNIL = 1);


///project this one as an attribute with XMLNIL=1
Property Property4 As %String(XMLNIL=1,XMLPROJECTION="ATTRIBUTE");

}

このクラスの新しいインスタンスを作成し (いずれのプロパティにも値を設定せず)、%XML.WriterOpens in a new tab を使用してその出力を生成する場合、以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<Test>
  <Property3 xsi:nil="true" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</Test>

例 : RuntimeIgnoreNull が 1

この例では、ライターの RuntimeIgnoreNull プロパティを 1 に設定します。1 つ前の例で使用したものと同じオブジェクトの出力を生成する場合、以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<Test Property2="" Property4="">
  <Property1></Property1>
  <Property3></Property3>
</Test>

この場合、RuntimeIgnoreNull が 1 なので、XMLNIL パラメータは使用されません。代わりに、空属性または空要素として "" がエクスポートされます。

タイプ情報のエクスポート

XML ライターは、既定ではタイプ情報を記述しません。出力にタイプ情報を追加するには、次の 2 つの方法を使用できます。

  • ライターの OutputTypeAttribute プロパティ。このプロパティが 1 の場合は、ライターは、記述するオブジェクト内のすべての要素の XML タイプ情報を追加します (これらのオブジェクト自体のタイプ情報は除く)。以下はその例です。

    <?xml version="1.0" encoding="UTF-8"?>
    <Root xmlns:s="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Person>
        <Name xsi:type="s:string">Petersburg,Greta U.</Name>
        <DOB xsi:type="s:date">1949-05-15</DOB>
      </Person>
    </Root>

    XML ドキュメントのルートに適切なネームスペースが追加されていることに注目してください。

  • Object() メソッドと RootObject() メソッドの className 引数。この引数を使用して、オブジェクト (クラス名) の想定される ObjectScript タイプを指定します。

    この引数が実際のタイプと同じ場合は、ライターはオブジェクトのタイプ情報を追加しません。

    この引数が実際のタイプと異なる場合は、ライターはオブジェクトの実際の XML タイプを追加します (既定ではクラス名)。例えば、Test2.PersonWithAddress のインスタンスの出力を記述して、className 引数の値として MyPackage.MyClass を指定するとします。MyPackage.MyClass は実際のクラス名とは異なるため、ライターは次の出力を生成します。

    <?xml version="1.0" encoding="UTF-8"?>
    <PersonWithAddress xsi:type="PersonWithAddress" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Name>Avery,Robert H.</Name>
      <Address>
        <City>Ukiah</City>
        <Zip>82281</Zip>
      </Address>
    </PersonWithAddress>

    Object() メソッドと RootObject() メソッドの全引数のリストは、該当するクラス・リファレンスを参照してください。

SOAP でエンコードされた XML の生成

%XML.WriterOpens in a new tab クラスの場合は、Format プロパティは、出力全体の形式を制御します。これは、以下のいずれかです。

  • 既定値であり、このドキュメントのほとんどの例で使用されている "literal"

  • SOAP 1.1 規格で説明されている方法でエンコードされている "encoded"

  • SOAP 1.2 規格で説明されている方法でエンコードされている "encoded12"

インライン参照の作成

エンコードされた形式では、任意のオブジェクト値プロパティが参照として含められ、参照オブジェクトが個別の要素としてエクスポートされます。

こうしたプロパティを個別の要素としてではなく、インラインでエクスポートするには、(ライターの) ReferencesInline プロパティを 1 に設定します。

Format"literal" に設定すると、ReferencesInline プロパティには何の効果もなくなります。

エクスポート後のアンスウィズルの制御

XML 対応の永続的なオブジェクトをエクスポートすると、通常どおり、必要な情報がすべて、メモリに自動的にスウィズルされます。この情報にはオブジェクト値プロパティが含まれています。オブジェクトをエクスポートしたら、いずれのオブジェクト・リストもアンスウィズルされますが、(既定では) 単一のオブジェクト参照はアンスウィズルされません。大きなオブジェクトの場合は、<STORE> エラーが発生する可能性があります。

このシナリオで、いずれの単一オブジェクト参照もアンスウィズルされるようにするには、XML 対応のクラスで XMLUNSWIZZLE パラメータを以下のように設定します。

Parameter XMLUNSWIZZLE = 1;

このパラメータの既定値は 0 です。

要素を閉じる形式の制御

属性のみを含む要素は、以下のいずれかで示すことができます。

<myelementname attribute="value" attribute="value" attribute="value"></myelementname>
<myelementname attribute="value" attribute="value" attribute="value"/>

Object() メソッドは常に、最初の構文で要素をエクスポートします。ここに示す 2 番目の構文で要素を閉じる必要がある場合は、この章で前述の “要素の手動作成” で説明しているように、オブジェクトを手動で記述します。

ライターのその他のオプション

ここでは、%XML.WriterOpens in a new tab で提供されるその他のオプションについて説明します。

Canonicalize() メソッド

Canonicalize() メソッドは、XML ノードを正規化された形式で記述します。このメソッドには、以下のシグニチャがあります。

method Canonicalize(node As %XML.Node, ByRef PrefixList, formatXML As %Boolean = 0) as %Status

以下はその説明です。

  • node はドキュメントのサブツリーであり、%XML.NodeOpens in a new tab のインスタンスとして、“XML ドキュメントの DOM 表現” の章で説明されています。

  • PrefixList は、以下のいずれかです。

    • 包含的な正規化の場合は、PrefixList"c14n" と指定します。この場合は、http://www.w3.org/TR/xml-c14nOpens in a new tab で指定されたとおり、出力は XML Canonicalization バージョン 1.0 で指定された形式となります。

    • 排他的な正規化の場合は、ノードを以下のようにして PrefixList を多次元配列と指定します。

      ノード
      PrefixList(prefix)prefix はネームスペース接頭語です。 このネームスペース接頭語と併用されるネームスペース

      この場合は、http://www.w3.org/TR/xml-exc-c14n/Opens in a new tab で指定されたとおり、出力は Exclusive XML Canonicalization バージョン 1.0 で指定された形式となります。

  • formatXML により形式を制御します。formatXML が True の場合、ライターは XML 正規化仕様による指定フォーマットではなく、ライター・インスタンス用の指定フォーマットを使用します。その際の出力はキャノニック XML ではありませんが、キャノニック XML 用のネームスペース処理が行われることになります。このオプションは、Web サービスの ProcessBodyNode() コールバックの SOAP 本文など、XML ドキュメントのフラグメント出力に役立ちつつ、一部のフォーマット制御を維持し続けます。

Shallow プロパティ

ライター・インスタンスの Shallow プロパティは、オブジェクト値を持つ出力プロパティに影響します。このクラスのプロパティを使用すると、オブジェクト値を持つすべての出力を小型化できます。つまり、参照先オブジェクトの詳細ではなく、参照先オブジェクトの ID が出力に記述されます。このプロパティと、XML 対応オブジェクトの XMLDEFAULTREFERENCEOpens in a new tab クラス・パラメータおよび XMLREFERENCEOpens in a new tab プロパティ・パラメータとの間には、以下のテーブルに示す相互関係があります。このテーブルは、各ケースごとに得られる出力を示しています。

Shallow = 1 の場合の影響
XMLREFERENCE および XMLDEFAULTREFERENCE の値 Shallow=1 の場合の出力
プロパティ・パラメータ "XMLREFERENCE""SUMMARY" または "COMPLETE" このプロパティについては出力なし
プロパティ・パラメータ XMLREFERENCE"ID""OID"、または "GUID" このプロパティについて、ID、OID、または GUID のうち、適切なタイプの出力を生成
プロパティ・パラメータ XMLREFERENCE が未設定で、クラス・パラメータ XMLDEFAULTREFERENCE"SUMMARY" または "COMPLETE" このプロパティについては出力なし
プロパティ・パラメータ XMLREFERENCE が未設定で、クラス・パラメータ XMLDEFAULTREFERENCE"ID""OID"、または "GUID" このプロパティについて、ID、OID、または GUID のうち、適切なタイプの出力を生成
プロパティ・パラメータ XMLREFERENCE およびクラス・パラメータ XMLDEFAULTREFERENCE がどちらも未設定 このプロパティについては出力なし

Shallow プロパティは、値にシリアル・オブジェクトを持つプロパティ、およびオブジェクト値ではない値を持つプロパティには影響を及ぼしません。

オブジェクトの XML への投影” の “オブジェクト値プロパティのプロジェクションが持つ形式の制御” も参照してください。

Summary プロパティ

ライター・インスタンスの Summary プロパティは、XML 対応オブジェクト全体をエクスポートするか、その概要をエクスポートするかを制御します。以下の 2 つの値のいずれかを指定します。

  • 既定値である 0 を指定すると、オブジェクト全体がエクスポートされます。

  • 値 1 を指定すると、概要として指定されているプロパティがエクスポートされます。

"オブジェクトの XML への投影" で説明したように、オブジェクトの概要は XMLSUMMARYOpens in a new tab クラス・パラメータによって指定される、コンマ区切りのプロパティのリストです。

例えば、XML 対応の Person クラスの出力を生成すると、既定の出力が以下のようになるとします。

<Persons>
 <Person>
  <Name>Xenia,Yan T.</Name>
  <DOB>1986-10-21</DOB>
 </Person>
 <Person>
  <Name>Vivaldi,Ashley K.</Name>
  <DOB>1981-01-25</DOB>
 </Person>
</Persons>

ここで、XMLSUMMARY の値を Person クラスの "Name" に設定します。この場合に Summary プロパティを 1 に設定すると、出力は以下のようになります。

<Persons>
 <Person>
  <Name>Xenia,Yan T.</Name>
 </Person>
 <Person>
  <Name>Vivaldi,Ashley K.</Name>
 </Person>
</Persons>

Base64LineBreaks プロパティ

タイプが %BinaryOpens in a new tab または %xsd.base64BinaryOpens in a new tab のプロパティには、自動改行を含めることができます。このためには、ライター・インスタンスの Base64LineBreaks プロパティを 1 に設定します。この場合、ライター・インスタンスの自動改行/復改が 76 文字ごとに発生します。このプロパティの既定値は 0 です。

CycleCheck プロパティ

ライター・インスタンスの CycleCheck プロパティは、エラーを引き起こす可能性がある参照オブジェクト内のサイクル (エンドレス・ループ) の有無をライターが確認するかどうかを制御します。既定は 1 で、ライターがサイクルの有無を確認します。

サイクルがないことが確実な場合は、CycleCheck を 0 に設定するとパフォーマンスがわずかに向上します。

その他の例 : 設定に選択肢があるライター

以下のメソッドは、%XML.WriterOpens in a new tab のプロパティを試したいユーザには便利な場合があります。ライターの “バージョン” を指定する文字列である、入力引数を受け入れます。各ライターのバージョンは、ライター・インスタンスのプロパティの特定の設定に対応します。

Class Utils.Writer
{

/// given a "name", return a writer with those properties
ClassMethod CreateWriter(wname) As %XML.Writer
{
 set w=##class(%XML.Writer).%New()
 set w.Indent=1
 set w.IndentChars="   "
 if wname="DefaultWriter" {
  set w.Indent=0  ; set back to default
  }
 elseif wname="EncodedWriter" {
  set w.Format="encoded"
  }
 elseif wname="EncodedWriterRefInline" {
  set w.Format="encoded"
  set w.ReferencesInline=1
  }
 elseif wname="AttQualWriter" {
  set w.AttributeQualified=1
  }
 elseif wname="AttUnqualWriter" {
  set w.AttributeQualified=0 ; default
  }
 elseif wname="ElQualWriter" {
  set w.ElementQualified=1 ; default
  }
 elseif wname="ElUnqualWriter" {
  set w.ElementQualified=0
  }
 elseif wname="ShallowWriter" {
  set w.Shallow=1
  }
 elseif wname="SOAPWriter1.1" {
  set w.Format="encoded"
  set w.ReferencesInline=1
  }
 elseif wname="SOAPWriter1.2" {
  set w.Format="encoded12"
  set w.ReferencesInline=1
  }
 elseif wname="SummaryWriter" {
  set w.Summary=1
  }
 elseif wname="WriterNoXmlDecl" {
  set w.NoXMLDeclaration=1
  }
 elseif wname="WriterRefInline" {
  set w.ReferencesInline=1
  }
 elseif wname="WriterRuntimeIgnoreNull" {
  set w.RuntimeIgnoreNull=1
  }
 elseif wname="WriterSuppressXmlns" {
  set w.SuppressXmlns=1
  }
 elseif wname="WriterUTF16" {
  set w.Charset="UTF-16"
  }
 elseif wname="WriterWithDefNS" {
  set w.DefaultNamespace="www.Def.org"
  }
 elseif wname="WriterWithDefNSSuppressXmlns" {
  set w.DefaultNamespace="www.Def.org"
  set w.SuppressXmlns=1
  }
 elseif wname="WriterWithDtdSettings" {
  set w.DocType ="MyDocType"
  set w.SystemID = "http://www.mysite.com/mydoc.dtd"
  set w.PublicID = "-//W3C//DTD XHTML 1.0 Transitional//EN"
  set w.InternalSubset = "" 
  }
 elseif wname="WriterXsiTypes" {
  set w.OutputTypeAttribute=1
  }
 quit w
}

}

以下のフラグメントは、このメソッドを使用してドキュメントの例の生成に役立てる方法を示しています。

/// method to write one to a file
ClassMethod WriteOne(myfile,cls,element,wname,ns,local,rootns)
{
    set writer=..CreateWriter(wname)
    set mydir=..#MyDir
    set comment="Output for the class: "_cls
    set comment2="Writer settings: "_wname
    
    if $extract(mydir,$length(mydir))'="/" {set mydir=mydir_"/"}
    set file=mydir_myfile
    set status=writer.OutputToFile(file)
    if $$$ISERR(status) { do $System.Status.DisplayError(status) quit }

    set status=writer.WriteComment(comment)
    if $$$ISERR(status) { do $System.Status.DisplayError(status) quit }

    set status=writer.WriteComment(comment2)
...
}

出力にコメント行が 2 つ含まれることに注意してください。1 つは、ファイルに表示される XML 対応クラスの名前を示します。もう 1 つは、ファイルの生成に使用されるライター設定の名前を示します。出力ディレクトリは集中的に (パラメータで) 制御され、この汎用メソッドには RootElement() メソッドおよび Object() メソッドの両方に渡される引数が含まれます。

FeedbackOpens in a new tab