XML ドキュメントの DOM 表現
%XML.DocumentOpens in a new tab クラスと %XML.NodeOpens in a new tab クラスを使用して、任意の XML ドキュメントを DOM (ドキュメント・オブジェクト・モデル) として表現できます。その後、このオブジェクトをナビゲートして変更できます。新しい DOM を作成してオブジェクトに追加することもできます。
Note:
使用する任意の XML ドキュメントの XML 宣言にはそのドキュメントの文字エンコードを明記する必要があり、明記しておけば、ドキュメントは宣言どおりにエンコードされるようになります。文字エンコードが宣言されていない場合は、"入出力の文字エンコード" で説明されている既定値が使用されます。これらの既定値が正しくない場合は、XML 宣言を修正して、実際に使用されている文字セットを指定するようにします。
DOM として XML ドキュメントを開く
既存の XML ドキュメントを DOM として使用するために開くには、以下の手順を実行します。
-
%XML.ReaderOpens in a new tab クラスのインスタンスを作成します。
-
必要に応じて、このインスタンスの Format プロパティを指定して、インポートするファイルの形式を指定します。
既定では、XML ファイルはリテラル形式と想定されます。ファイルが SOAP でエンコードされた形式の場合は、そのように明記して、ファイルを正しく読み取れるようにする必要があります。
"オブジェクトへの XML のインポート" の "リーダ・プロパティ" を参照してください。
Correlate() と Next() を使用していない場合、このプロパティには何の効果もなくなります。
-
ソースを開きます。そのためには、%XML.ReaderOpens in a new tab の次のメソッドのいずれかを使用します。
いずれの場合も、オプションでメソッドに 2 番目の引数を指定して、Format プロパティの値をオーバーライドすることができます。
-
DOM である Document プロパティにアクセスします。このプロパティは %XML.DocumentOpens in a new tab のインスタンスであり、ドキュメント全体についての情報を見つけるのに使用できるメソッドを提供します。例えば、CountNamespace() は DOM で使用されるネームスペースの総数を返します。
または、XML ドキュメントを格納したストリームがある場合は、%XML.DocumentOpens in a new tab の GetDocumentFromStream() メソッドを呼び出します。これにより %XML.DocumentOpens in a new tab のインスタンスが返されます。
例 1 : ファイルの DOM への変換
例えば、以下のメソッドで XML ファイルを読み取り、そのドキュメントを表す %XML.DocumentOpens in a new tab のインスタンスを返します。
ClassMethod GetXMLDocFromFile(file) As %XML.Document
{
set reader=##class(%XML.Reader).%New()
set status=reader.OpenFile(file)
if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
set document=reader.Document
quit document
}
例 2 : オブジェクトの DOM への変換
以下のメソッドで OREF を受け入れ、そのオブジェクトを表す %XML.DocumentOpens in a new tab のインスタンスを返します。このメソッドでは、OREF は XML 対応のクラスのインスタンスと想定されます。
ClassMethod GetXMLDoc(object) As %XML.Document
{
//make sure this is an instance of an XML-enabled class
if '$IsObject(object){
write "Argument is not an object"
quit $$$NULLOREF
}
set classname=$CLASSNAME(object)
set isxml=$CLASSMETHOD(classname,"%Extends","%XML.Adaptor")
if 'isxml {
write "Argument is not an instance of an XML-enabled class"
quit $$$NULLOREF
}
//step 1 - write object as XML to a stream
set writer=##class(%XML.Writer).%New()
set stream=##class(%GlobalCharacterStream).%New()
set status=writer.OutputToStream(stream)
if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
set status=writer.RootObject(object)
if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
//step 2 - extract the %XML.Document from the stream
set status=##class(%XML.Document).GetDocumentFromStream(stream,.document)
if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
quit document
}
DOM のネームスペースの取得
InterSystems IRIS で XML ドキュメントを読み取り、DOM を作成するとき、ドキュメント内で使用されるすべてのネームスペースが識別され、それぞれにインデックス番号が割り当てられます。
%XML.DocumentOpens in a new tab クラスのインスタンスは、ドキュメント内のネームスペースについての情報を見つけるために使用できる以下のメソッドを提供します。
FindNamespace()
指定されたネームスペースに対応するインデックスを返します。
GetNamespace()
指定されたインデックスの XML ネームスペース URI を返します。
以下の例のメソッドは、ドキュメント内で使用されているネームスペースを示すレポートを表示します。
ClassMethod ShowNamespaces(doc As %XML.Document)
{
Set count=doc.CountNamespace()
Write !, "Number of namespaces in document: "_count
For i=1:1:count {
Write !, "Namespace "_i_" is "_doc.GetNamespace(i)
}
}
"現在のノードについての情報の取得" も参照してください。
DOM のノードのナビゲート
ドキュメントのノードにアクセスするには、以下の 2 つの手法を使用できます。
子ノードまたは兄弟ノードへの移動
子ノードまたは兄弟ノードに移動するには、%XML.NodeOpens in a new tab のインスタンスの以下のメソッドを使用します。
-
MoveToFirstChild()
-
MoveToLastChild()
-
MoveToNextSibling()
-
MoveToPreviousSibling()
これらの各メソッドは、(メソッド名で示されるように) 別のノードへの移動を試みます。移動が可能な場合、メソッドは True を返します。可能でない場合、メソッドは False を返し、フォーカスはメソッドが呼び出される前と同じ状態です。
これらの各メソッドには、オプションの引数 skipWhitespace があります。この引数が True の場合、メソッドは空白をすべて無視します。skipWhitespace の既定値は False です。
親ノードへの移動
現在のノードの親ノードに移動するには、%XML.NodeOpens in a new tab のインスタンスの MoveToParent() メソッドを使用します。
このメソッドはオプションの引数 restrictDocumentNode をとります。この引数が True の場合、メソッドはドキュメント・ノード (ルート) に移動しません。restrictDocumentNode の既定値は False です。
特定のノードへの移動
特定のノードに移動するために、%XML.NodeOpens in a new tab のインスタンスの NodeId プロパティを設定できます。以下はその例です。
set saveNode = node.NodeId
//..... lots of processing
//...
// restore position
set node.NodeId=saveNode
id 属性の使用
場合によっては、XML ドキュメントには id という名前の属性が含まれることがあります。これはドキュメント内の異なるノードを識別するために使用されます。以下はその例です。
<?xml version="1.0"?>
<team>
<member id="alpha">Jack O'Neill</member>
<member id="beta">Samantha Carter</member>
<member id="gamma">Daniel Jackson</member>
</team>
この例のようにドキュメントが id という属性を使用している場合、この属性を使用してそのノードに移動できます。このためには、そのノードの位置にある %XML.NodeOpens in a new tab のインスタンスを返す、ドキュメントの GetNodeById() メソッドを使用します。(他のほとんどの検索メソッドとは異なり、このメソッドは %XML.NodeOpens in a new tab ではなく %XML.DocumentOpens in a new tab から利用できることに注意してください。)
DOM ノード・タイプ
%XML.DocumentOpens in a new tab クラスと %XML.NodeOpens in a new tab クラスは、以下の DOM ノード・タイプを認識します。
その他のタイプの DOM ノードは無視されます。
以下の XML ドキュメントについて考えてみます。
<?xml version="1.0"?>
<team>
<member id="alpha">Jack O'Neill</member>
<member id="beta">Samantha Carter</member>
<member id="gamma">Daniel Jackson</member>
</team>
DOM として表示する際、このドキュメントには以下のノードが含まれます。
ドキュメント・ノードの例
NodeID |
NodeType |
LocalName |
メモ |
0,29 |
$$$xmlELEMENTNODE |
team |
|
1,29 |
$$$xmlWHITESPACENODE |
|
このノードは、<team> ノードの子です。 |
1,23 |
$$$xmlELEMENTNODE |
member |
このノードは、<team> ノードの子です。 |
2,45 |
$$$xmlTEXTNODE |
Jack O'Neill |
このノードは、最初の <member> ノードの子です。 |
1,37 |
$$$xmlWHITESPACENODE |
|
このノードは、<team> ノードの子です。 |
1,41 |
$$$xmlELEMENTNODE |
member |
このノードは、<team> ノードの子です。 |
3,45 |
$$$xmlTEXTNODE |
Samantha Carter |
このノードは、2 番目の <member> ノードの子です。 |
1,45 |
$$$xmlWHITESPACENODE |
|
このノードは、<team> ノードの子です。 |
1,49 |
$$$xmlELEMENTNODE |
member |
このノードは、<team> ノードの子です。 |
4,45 |
$$$xmlTEXTNODE |
Daniel Jackson |
このノードは、3 番目の <member> ノードの子です。 |
1,53 |
$$$xmlWHITESPACENODE |
|
このノードは、<team> ノードの子です。 |
ノード・タイプやローカル名などの詳細へのアクセスについては、次のセクションを参照してください。
現在のノードについての情報の取得
%XML.NodeOpens in a new tab の以下の文字列プロパティは、現在のノードについての情報を提供します。いずれの場合にも、現在のノードがないとエラーがスローされます。
LocalName
現在の要素ノードのローカル名。別のタイプのノードでこのプロパティにアクセスしようとすると、エラーがスローされます。
Namespace
現在の要素ノードのネームスペース URI。別のタイプのノードでこのプロパティにアクセスしようとすると、エラーがスローされます。
NamespaceIndex
現在の要素ノードのネームスペースのインデックス。
InterSystems IRIS で XML ドキュメントを読み取り、DOM を作成するとき、ドキュメント内で使用されるすべてのネームスペースが識別され、それぞれにインデックス番号が割り当てられます。
別のタイプのノードでこのプロパティにアクセスしようとすると、エラーがスローされます。
Nil
この要素ノードに対して xsi:nil または xsi:null が True または 1 の場合は True になります。それ以外の場合、このプロパティは False になります。
NodeId
現在のノードの ID。別のノードに移動するために、このプロパティを設定できます。
QName
要素ノードの Qname。接頭語がドキュメントで有効な場合に、XML としての出力のみに使用されます。
以下のメソッドは、現在のノードについての追加情報を提供します。
GetText()
method GetText(ByRef text) as %Boolean
要素ノードのテキスト・コンテンツを取得します。テキストが返される場合、このメソッドは True を返します。この場合、実際のテキストは参照渡しの最初の引数に追加されます。
HasChildNodes()
method HasChildNodes(skipWhitespace As %Boolean = 0) as %Boolean
現在のノードに子ノードがある場合に True を返します。それ以外の場合は False を返します。
GetNumberAttributes()
method GetNumberAttributes() as %Integer
現在の要素の属性の番号を返します。
例
以下の例のメソッドは、現在のノードについての情報を提供するレポートを記述します。
ClassMethod ShowNode(node as %XML.Node)
{
Write !,"LocalName="_node.LocalName
If node.NodeType=$$$xmlELEMENTNODE {
Write !,"Namespace="_node.Namespace
}
If node.NodeType=$$$xmlELEMENTNODE {
Write !,"NamespaceIndex="_node.NamespaceIndex
}
Write !,"Nil="_node.Nil
Write !,"NodeData="_node.NodeData
Write !,"NodeId="_node.NodeId
Write !,"NodeType="_node.NodeType
Write !,"QName="_node.QName
Write !,"HasChildNodes returns "_node.HasChildNodes()
Write !,"GetNumberAttributes returns "_node.GetNumberAttributes()
Set status=node.GetText(.text)
If status {
Write !, "Text of the node is "_text
} else {
Write !, "GetText does not return text"
}
}
出力例は以下のようになります。
LocalName=staff
Namespace=
NamespaceIndex=
Nil=0
NodeData=staff
NodeId=1
NodeType=e
QName=staff
HasChildNodes returns 1
GetNumberAttributes returns 5
GetText does not return text
属性の検証のための基本的なメソッド
%XML.NodeOpens in a new tab の以下のメソッドを使用して、現在のノードの属性を検証できます。"属性の検証のためのその他のメソッド" も参照してください。
-
AttributeDefined() — 現在の要素が指定した名前の属性を持つ場合、ゼロ以外 (True) を返します。
-
FirstAttributeName() — 現在の要素の最初の属性の属性名を返します。
-
GetAttributeValue() — 指定した属性の値を返します。要素に属性がない場合、メソッドは Null を返します。
-
GetNumberAttributes() — 現在の要素の属性の番号を返します。
-
LastAttributeName() — 現在の要素の最後の属性の属性名を返します。
-
NextAttributeName() — 属性名を指定すると、指定した属性が有効かどうかにかかわらず、このメソッドは照合順の次の属性の名前を返します。
-
PreviousAttributeName() — 属性名を指定すると、指定した属性が有効かどうかにかかわらず、このメソッドは照合順の前の属性の名前を返します。
以下の例は、指定したノードの属性を参照し、簡単なレポートを記述します。
ClassMethod ShowAttributes(node as %XML.Node)
{
Set count=node.GetNumberAttributes()
Write !, "Number of attributes: ", count
Set first=node.FirstAttributeName()
Write !, "First attribute is: ", first
Write !, " Its value is: ",node.GetAttributeValue(first)
Set next=node.NextAttributeName(first)
For i=1:1:count-2 {
Write !, "Next attribute is: ", next
Write !, " Its value is: ",node.GetAttributeValue(next)
Set next=node.NextAttributeName(next)
}
Set last=node.LastAttributeName()
Write !, "Last attribute is: ", last
Write !, " Its value is: ",node.GetAttributeValue(last)
}
以下の XML ドキュメントの例について考えてみます。
<?xml version="1.0"?>
<staff attr1="first" attr2="second" attr3="third" attr4="fourth" attr5="fifth">
<doc>
<name>David Marston</name>
</doc>
</staff>
このドキュメントの最初のノードをメソッド例に渡すと、以下の出力が表示されます。
Number of attributes: 5
First attribute is: attr1
Its value is: first
Next attribute is: attr2
Its value is: second
Next attribute is: attr3
Its value is: third
Next attribute is: attr4
Its value is: fourth
Last attribute is: attr5
Its value is: fifth
属性の検証のためのその他のメソッド
このセクションでは、属性の名前、値、ネームスペース、QName、および値ネームスペースを取得するのに使用できるメソッドについて説明します。これらのメソッドは以下のとおりに分類されます。
"属性の検証のための基本的なメソッド" も参照してください。
属性名のみを使用するメソッド
属性についての情報を取得するには以下のメソッドを使用します。
GetAttribute()
method GetAttribute(attributeName As %String,
ByRef namespace As %String,
ByRef value As %String,
ByRef valueNamespace As %String)
指定した属性のデータを返します。このメソッドは、参照により以下の値を返します。
-
namespace は、属性の QName からのネームスペース URI です。
-
value は属性値です。
-
valueNamespace は、その値が属するネームスペース URI です。例えば、以下の属性を考えてみます。
xsi:type="s:string"
この属性の値は string であり、この値は、別の場所で宣言され、接頭語を s とするネームスペースの中にあります。このドキュメントの既述部分に、以下のネームスペース宣言があったとします。
xmlns:s="http://www.w3.org/2001/XMLSchema"
この場合、valueNamespace は "http://www.w3.org/2001/XMLSchema" となります。
GetAttributeNamespace()
method GetAttributeNamespace(attributeName As %String) as %String
現在の要素の attributeName という名前の属性の QName から、ネームスペース URI を返します。
GetAttributeQName()
method GetAttributeQName(attributeName As %String) as %String
指定した属性の QName を返します。
GetAttributeValue()
method GetAttributeValue(attributeName As %String) as %String
指定した属性の値を返します。
GetAttributeValueNamespace()
method GetAttributeValueNamespace(attributeName As %String) as %String
指定した属性の値のネームスペースを返します。
属性名とネームスペースを使用するメソッド
名前とネームスペースの両方を使用して属性についての情報を取得するには、以下のメソッドを使用します。
GetAttributeNS()
method GetAttributeNS(attributeName As %String,
namespace As %String,
ByRef value As %String,
ByRef valueNamespace As %String)
指定した属性のデータを返します。attributeName および namespace で目的の属性を指定します。このメソッドは、参照により以下のデータを返します。
-
value は属性値です。
-
valueNamespace は、その値が属するネームスペース URI です。例えば、以下の属性を考えてみます。
xsi:type="s:string"
この属性の値は string であり、この値は、別の場所で宣言され、接頭語を s とするネームスペースの中にあります。このドキュメントの既述部分に、以下のネームスペース宣言があったとします。
xmlns:s="http://www.w3.org/2001/XMLSchema"
この場合、valueNamespace は "http://www.w3.org/2001/XMLSchema" となります。
GetAttributeQNameNS()
method GetAttributeQNameNS(attributeName As %String,
namespace As %String)
as %String
指定した属性の QName を返します。attributeName および namespace で目的の属性を指定します。
GetAttributeValueNS()
method GetAttributeValueNS(attributeName As %String,
namespace As %String)
as %String
指定した属性の値を返します。attributeName および namespace で目的の属性を指定します。
GetAttributeValueNamespaceNS
method GetAttributeValueNamespaceNS(attributeName As %String,
namespace As %String)
as %String
指定した属性の値のネームスペースを返します。attributeName および namespace で目的の属性を指定します。
DOM の作成または編集
DOM を作成するか既存の DOM を変更するには、%XML.DocumentOpens in a new tab の以下のメソッドを使用します。
AppendCharacter()
method AppendCharacter(text As %String)
新しい文字データ・ノードをこの要素ノードの子のリストに追加します。現在のノードのポインタは変更されません。このノードは追加された子の親のままです。
AppendChild()
method AppendChild(type As %String)
新しいノードをこのノードの子のリストに追加します。現在のノードのポインタは変更されません。このノードは追加された子の親のままです。
AppendElement()
method AppendElement(localName As %String,
namespace As %String,
text As %String)
新しい要素ノードをこのノードの子のリストに追加します。テキストの引数が指定されると、文字データが新しい要素の子として追加されます。現在のノードのポインタは変更されません。このノードは追加された子の親のままです。
AppendNode()
method AppendNode(sourceNode As %XML.Node) as %Status
このノードの子として、指定したノードのコピーを追加します。コピーするノードは、任意のドキュメントをコピー元にできます。現在のノードのポインタは変更されません。このノードは追加された子の親のままです。
AppendTree()
method AppendTree(sourceNode As %XML.Node) as %Status
このノードの子として、指定したノードの (すべての子を含む) コピーを追加します。コピーするツリーは任意のドキュメントをコピー元にできますが、ソース・ノードの下位ノードをこのノードにすることはできません。現在のノードのポインタは変更されません。このノードは追加された子の親のままです。
InsertNamespace()
method InsertNamespace(namespace As %String)
指定されたネームスペース URI をドキュメントに追加します。
InsertCharacter()
method InsertCharacter(text as %String, ByRef child As %String, Output sc As %Status) as %String
このノードの子として、新しい文字データ・ノードを挿入します。新しい文字データは、指定した子ノードの直前に挿入されます。child 引数は、子ノードのノード ID です。これは参照によって渡されるため、挿入後に更新される可能性があります。挿入されたノードの NodeId が返されます。現在のノードのポインタは変更されません。
InsertNode()
method InsertNode(sourceNode As %XML.Node, ByRef child As %String, Output sc As %Status) as %String
このノードの子として、指定したノードのコピーを挿入します。コピーするノードは、任意のドキュメントをコピー元にできます。新規ノードは、指定した子ノードの直前に挿入します。child 引数は、子ノードのノード ID です。これは参照によって渡されるため、挿入後に更新される可能性があります。挿入されたノードの NodeId が返されます。現在のノードのポインタは変更されません。
InsertTree()
method InsertTree(sourceNode As %XML.Node, ByRef child As %String, Output sc As %Status) as %String
このノードの子として、指定したノードの (その子を含む) コピーを挿入します。コピーするツリーは任意のドキュメントをコピー元にできますが、ソース・ノードの下位ノードをこのノードにすることはできません。新規ノードは、指定した子ノードの直前に挿入します。child 引数は、子ノードのノード ID です。これは参照によって渡されるため、挿入後に更新される可能性があります。挿入されたノードの NodeId が返されます。現在のノードのポインタは変更されません。
Remove()
method Remove()
現在のノードを削除し、その親を現在のノードにします。
RemoveAttribute()
method RemoveAttribute(attributeName As %String)
指定された属性を削除します。
RemoveAttributeNS()
method RemoveAttributeNS(attributeName As %String,
namespace As %String)
指定した属性を削除します。attributeName および namespace で目的の属性を指定します。
ReplaceNode()
method ReplaceNode(sourceNode As %XML.Node) as %Status
ノードを、指定したノードのコピーで置き換えます。コピーするノードは、任意のドキュメントをコピー元にできます。現在のノードのポインタは変更されません。
ReplaceTree()
method ReplaceTree(sourceNode As %XML.Node) as %Status
ノードを、指定したノードの (そのすべての子を含む) コピーで置き換えます。コピーするツリーは任意のドキュメントをコピー元にできますが、ソース・ノードの下位ノードにすることはできません。現在のノードのポインタは変更されません。
SetAttribute()
method SetAttribute(attributeName As %String,
namespace As %String = "",
value As %String = "",
valueNamespace As %String = "")
現在の要素の属性のデータを設定します。以下はその説明です。