メインコンテンツまでスキップ

SenseTalkスクリプトでXMLとツリー構造を使用する

SenseTalkのツリー構造は、XML形式のデータを簡単に読み取り、ツリー内のデータにアクセスして操作し、そのデータからXMLを生成する能力を提供します。ツリーは、リストとプロパティリスト(いくつかの制限あり)の両方として動作する階層的なデータ構造です。リストとして、ツリーはアイテムを含み、これらのアイテムはノードとも呼ばれ、それ自体がツリーです。プロパティリストとして、ツリーはXML用語でのノードの属性に対応するプロパティを持ちます。

ツリーとノード

ツリーは、任意の数の ノードを持つことができる ルートノード からなる階層です。各子ノード自体が任意の数の子ノードを持つことができるツリーであり、そのように任意の深さまで続くことができます。各ノード(ルートノードを除く)は ノードを持ち、これはそのノードを子として含むツリー(またはサブツリー)です。

親ノードとゼロ以上の子ノードを持つことに加えて、各ノードはタグ名を含む数個のプロパティまたは属性を持つことができます。

ツリーの基本構造は次のようになります:

ツリーの各ノードは自身の子ノードを持つことができるので、各ノード(その子とその後の子孫とともに)自体がツリーとなります。

ツリーとXML

ツリーは各種の階層データを保存するのに便利ですが、SenseTalkのツリー構造は特にXMLドキュメントやXMLベースのデータを扱うために設計されています。eXtensible Markup Language(XML)は、現在使用されている多種多様なデータ形式の基盤となる豊富で柔軟で複雑な言語です。

SenseTalkのツリー構造はXMLドキュメントやデータ構造の操作を簡単にし、個々の値に簡単にアクセスできるようにするとともに、必要に応じてドキュメントのすべての部分にフルアクセスを提供します。

XMLの構造とその一部の用語を少なくとも基本的に理解すると、ツリーとそのXMLとの関係を完全に理解するのに役立ちます。以下の例のXMLドキュメントを考えてみてください:

<?xml version="1.0?>
<order id ="001">
<customer name="Janet Brown"/>
<product code="prod345" size="6">
<quantity>3</quantity>
<amount>23.45</amount>
</product>
</order>

上記の例では、最初の行はこれがバージョン1.0のXMLドキュメントであることを特定します。二番目と最後の行は、残りのコンテンツを order タグで囲みます。この全体のセクションは、customerproduct の2つの他の要素を含む ドキュメント ノード(上記の例のように)または 要素 ノード(XMLバージョン情報が欠けている場合)を構成します。customer 要素には name 属性 がありますが、追加のコンテンツはありません。 product 要素には codesize の属性があり、さらに2つの要素、quantityamount を含みます。 quantityamount の両方の要素には、テキストノード として知られる囲まれたテキストが含まれています。

この情報をツリーで表現すると、次のようになります:

括弧内の情報は、ノードの種類と、そのノードに存在する場合の属性を示しています。ツリー形式では、orderノードが2つの子供(customerとproduct)を持ち、productノードもまた2つの子供(quantityとamount)を持っていることがわかります。quantityとamountノードはそれぞれ一つの子供:対応する値を持つテキストノードを持っています。

XMLデータは主に要素で構成されていることに注意してください(ドキュメントノードは特別な種類の要素として扱うことができます)。各要素にはタグ(ordercustomerproductなどのタグ)、属性(idnamecodeなどの属性)があり、子供がいるかもしれません。子供たちは要素であるかもしれませんし、単純なテキスト値(323.45)であるかもしれません。他のノードタイプもありますが、それらはあまり一般的ではなく、この例では示されていません。

ここに示したorderの例は、現在使用されている多くのXMLフォーマットの典型的なものです。要素、属性、テキストをネストした構造に組み合わせることで、XMLは様々なフォーマットと、それらの中のバリエーションを可能にします。

ツリー = リスト + プロパティリスト

SenseTalkがツリーと共に働くアプローチは、ツリーを両方のコンテナタイプのハイブリッドとして扱うことで、リストとプロパティリストを扱うための言語固有の機能を活用しています。ツリーの子供はリストのアイテムのようにアクセスでき、その属性はプロパティリストのプロパティ値のようにアクセスできます。

ツリーについてはいくつかの詳細が異なります(以下で説明しますが)、全体として、リストとプロパティリストの扱いに慣れているなら、ツリーを扱うために必要なことのほとんどをすでに知っています。詳細はListsProperty Listsを参照してください。

ツリーにはこれらの特性があるため、XMLとは何も関係がない状況でも、リストとプロパティリストの両方として動作するハイブリッドコンテナタイプとして役立つかもしれません。

ツリーとの作業

XMLからツリーを作成する

スクリプト内の内部ツリー構造にXMLデータを含むURLの内容をロードするには、as a tree演算子を使用します:

put url "http://some.site/data.xml" as a tree into myTree

この文は指定されたURLにアクセスし、その内容を読み取ります。as a tree演算子はSenseTalkにそのデータをXMLドキュメントとして扱い、それをツリー構造に変換し、その後変数myTreeに格納するように指示します。

スクリプトに直接含まれるXMLから始めることが便利かもしれません。as tree演算子はこれにも同じように動作します:

set XMLSource to {{
<order id="001">
<customer name="Janet Brown"/>
<product code="prod345" size="6">
<quantity>3</quantity>
<amount>23.45</amount>
</product>
</order>
}}
}}
// XMLSource内のXML情報をツリーフォーマットの変数orderに格納します

以下の他の例では、このorderツリーが参照されています。

ツリーからXMLを作成する

ツリーのデータからXML形式のテキストを生成することは、XMLテキストからツリーを作成することよりも簡単です。ツリー構造がテキストとして使用されると、ツリーの内容のXML表現が自動的に作成されます。ツリーからXMLファイルを作成するには、たとえば、この構文を使用します:

put myTree into file "/path/to/aFile.xml"

ツリーの内容へのアクセス

ツリーの子は、リストのアイテムと同じようにアクセスできます。以下の例では、上述の as tree 構造例からの情報を使用します:

put item 1 of order

上記のコマンドを実行すると、次の結果が得られます:

ツリーの属性は、プロパティリストのプロパティと同じようにアクセスできます:

put order.id

上記のコマンドを実行すると、次の結果が得られます:001

アイテムとプロパティを組み合わせると、より深くネストされたデータにアクセスできます:

put the code of item 2 of order

上記のコマンドを実行すると、次の結果が得られます:prod345

XPath式を使用したツリーノードへのアクセス

XPathは、XMLドキュメントのコンテンツにアクセスするための標準的なメカニズムです。興味のあるノードやノードのセットを記述し、所望の情報を抽出する方法を提供します。SenseTalkは、この強力なメカニズムをnode表現を通じてサポートします。これにより、タグ名によってツリー内のコンテンツにアクセスできます:

put node "*/customer" of order

上記のコマンドを実行すると、次の結果が得られます:

ノード表現は、ツリーのネストされたノードへのパスを記述できます:

put node "*/product/amount" of order

上記のコマンドを実行すると、次の結果が得られます: 23.45

特別なtextプロパティは、ツリーやノードのコンテンツだけを抽出するのに役立ちます:

put the text of node "*/product/amount" of order

上記のコマンドを実行すると、次の結果が得られます:23.45

all nodesまたはevery nodeを使用して、XPath式に一致するツリーのすべてのノードのリストを返します:

put all nodes "*/product/*" of order

上記のコマンドを実行すると、次の結果が得られます: (3,23.45)

put everynode "*/*/amount" of order

上記のコマンドを実行すると、次の結果が得られます:23.45)

nodePath関数は、ツリー内の特定のノードのXPath式を返します:

put nodepath of item 2 of item 2 of order

上記のコマンドを実行すると、次の結果が得られます:(/order[1]/product[1]/amount[1])

node表現(ただし、all nodesは除く)は、ツリーの内容を変更するためのコンテナとしても使用できます:

put 7 into node "*/product/quantity" of order

上記のコマンドを実行すると、quantityの値が3から7に置き換えられます。変更が成功したことを確認するには、以下のコマンドを実行します:

put node "*/*/quantity" of order

次の出力を確認して、3が7に置き換えられたことを確認します: 7

XPath式には、特定のノードにアクセスするためのさまざまなオプションが含まれていますが、ここではその一部しか示されていません。XPathの使用についての詳細は、XPath Definition または XML Path Language (XPath)の完全な仕様を参照してください。

ノード表現を使用したツリーノードの削除

ノード表現を使用してツリーノードを削除できます(以前は、deleteコマンドでツリーノードを削除するためにアイテム表現のみが機能していました):

delete node "product/description" of order

3つの特別なプロパティ:_tag_children_attributes

ツリーには特別な意味を持つプロパティ名(すべてアンダースコアで始まる)がいくつかあります。最も重要な3つは以下のとおりです:

_tag プロパティは要素のタグ名を参照します。

_children プロパティはツリーの子を参照します。その値は、すべての子ツリーを含む通常のリストです。

_attributes プロパティはツリーの属性を参照します。その値は、キーと値がツリーのすべての属性の名前と値である通常のプロパティリストです。_attributesプロパティを通じて、特別なツリープロパティと同じ名前を持つものを含む、ツリーの任意の属性にアクセスできます。

_tag_children_attributesプロパティに加えて、ドキュメントノードには、以下のツリーをテキストに変換するで説明されているような_xmlinfoプロパティを持つこともあります。

空のツリーの作成

既存のXMLドキュメントから始めるのではなく、スクリプト内で完全にツリーを作成するには、コンテンツを追加できる空のツリーから始めます:

put an empty tree into order

この文によって生成されるツリーは、子または属性を受け入れる準備ができています。タグ名がないため、推奨される次のステップは、その_tagプロパティを設定することです:

set order's _tag to "order"

ツリーのXML属性の設定

ツリーのプロパティは、XML要素の「属性」に対応しています。これらはコンテナであり、プロパティリストのプロパティが設定されるのと同じように設定できます:

set order's id to "001"

ツリーのプロパティを設定する際の唯一の制限は以下のとおりです:

  • 値は常に設定時にテキストに変換されます。

  • プロパティ名は、標準的なXML識別子のルール(SenseTalkの識別子と同じ)に準拠しなければなければなりません:

    • 文字またはアンダースコアで始まる必要があります。
    • 文字、アンダースコア、数字のみを含む必要があります。

ツリーに子を追加する

ツリーの子は、リストのアイテムのようにアクセスされます。新しい子を追加するには、insertコマンドを使用します:

insert << <customer name="Jane Doe"/> >> into order

変更が正常に行われたことを確認するために、次のコマンドを実行します:

put every node "*/customer" of order

次の結果を探します:(

子はツリーでなければならず、またはツリーに変換できる値でなければなりません。値は、tree関数の同じルールを使用してツリーに追加されるときに自動的に変換されます。このセクションの後半で説明されています。DocumentElementDTDnodeTypeを持つノードのみが子を持つことができます。他のタイプのノードには子がいないため、リストのように動作しません。

ツリーをテキストに変換する

ツリーがテキストとしてアクセスされると(putコマンドで表示されるなど)、SenseTalkはそれを自動的にXML形式のテキスト表現に変換します。the treeFormat's prettyPrinttrueまたはfalseに設定することで、XMLが人間が読みやすいように複数の行にインデント付きでフォーマットされるかどうかを制御できます。デフォルトでは、そのプロパティはtrueに設定されています。standardFormat()関数もまた、ツリーをテキストとしてフォーマットするために使用できます。

ツリーがドキュメントレベルの情報(_xmlinfoプロパティで定義される)を持っている場合、それはツリーのテキスト表現を生成するために使用されます。_xmlinfoプロパティはツリーのトップレベル(サブツリーではない)でのみ設定できるため、ツリーを他のツリーのサブツリーとして挿入すると、そのドキュメントレベルの情報が破棄されます。_xmlinfoプロパティは、以下のドキュメントレベルのプロパティを含むことができるプロパティリストです:

  • CharacterEncoding – 設定されている場合、これは有効なXMLエンコーディングの名前であるべきです(有効なエンコーディング名のリストについては、キャラクターセット(IANA)を参照してください - これらはSenseTalkの文字列エンコーディングタイプとは異なります)。
  • DocumentContentType – XML、XHTML、HTML、またはテキストのいずれかでなければならない。これはそのツリーのために生成されるテキスト表現の一部の側面を制御する。
  • MIMEType – 有効なMIMEタイプに設定すべきです(メディアタイプ(IANA)を参照してください)。
  • URI – そのドキュメントに関連付けられたUniform Resource Identifier(通常はURL)。
  • Version – XMLのバージョンを示すために、1.0または1.1のいずれかにするべきです。

さらに、_xmlinfoは、ドキュメントのルート要素の前後にあるコメントまたは処理命令のツリーノードのリストを含むこともできます:

  • Head – ルート要素の前にあるコメントと処理命令のリスト
  • Tail – ルート要素の後にあるコメントと処理命令のリスト

プロパティリストからツリーを作成する

スクリプトの情報をプロパティリストの形で表現し、それをツリーに変換してXML出力を生成すると便利かもしれません。SenseTalkのtree関数(またはasTree()またはas a treeオペレータ)は、これを便利にするためにいくつかの形式のプロたリストをサポートしています。

完全な標準形式では、プロパティリストには以下の特殊なプロパティ(および値)を含めることができます:_tagまたは**_element**(要素のタグ名);_attributes(要素ノードの属性のプロパティリスト);_children(子ノードのリスト);_text(テキストノードの内容);_commentまたは**--(コメントノードの内容);_processingInstructionまたは_pi**(処理命令ノードの内容);?に続く処理命令名(処理命令ノードの本体);_XMLinfo(特殊なXMLドキュメント属性のプロパティリスト)。以下にこのアプローチを使用した簡単な例を示します:

put (_tag:book,_children:"The Rose") as tree
-- <book>The Rose</book>

XML属性が必要ない場合には、簡略化した形式を使用することができます:

put {book:"The Rose"} as tree
-- <book>The Rose </book>

いくつかのXML形式は属性を使用しますが、コンテンツは必要ありません。これは以下のように行うことができます:

put tree(_tag:"pg",_attributes:{id:43}) -- <pg id="43"></pg>

このケースでも簡略化した形式を使用することができます:

put tree(_tag:"pg", id:43)-- <pg id="43"></pg>

プロパティリストをツリーに変換するルールは次のようにまとめることができます:特殊なプロパティでない単一のプロパティがある場合、そのプロパティ名は要素の名前とみなされ、その値はその要素の子を表現します。プロパティリストに**_tagまたは_elementプロパティがある場合、それは要素ノードを生成します。この場合、_attributes**プロパティがなければ、特殊な意味を持たない他のプロパティは属性とみなされます。

リストからツリーを作成する

tree関数(またはasTree()またはas a treeオペレーター)を使用して、リストをツリーに変換することも可能です。この方法で変換されると、リストは名前のないツリー(タグが空)になります。これは、変換されるプロパティリスト内のネストされたリストやリストにも適用されます。

ツリーをプロパティリストに変換する

ツリーは、asオペレーターを使用してプロパティリストに変換することもできます。例えば:

put "<zip>80521</zip>" as tree as object -- {zip:(80521)}

可能であれば、SenseTalkはプロパティリストの簡略化された形式を使用します。すべての場合で標準形式を生成するには、the treeFormat's useStandardFormatプロパティをtrueに設定します:

set the treeFormat's useStandardFormat to true
put "<zip>80521</zip>" as tree as object
-- (_children:({_text:"80521"}), _tag:"zip")

ツリーの比較

二つの値が等しいかどうかを比較するとき(isまたは=オペレーターを使用して)、通常はテキストとして比較されます。両方の値がツリー(ツリーフォーマットで、プロパティリストやXMLテキスト表現のツリーではない)の場合にのみ、ツリーとして比較されます。ツリーでない値に対してas treeを指定することで、ツリーとしての比較を強制することができます。

一つのツリーが別のツリーと比較されるとき、二つのツリーは、同一の子とプロパティを含む場合に同一とみなされます。しかし、二つのツリーがほとんど同一で、唯一の違いが、一方のツリーにデフォルト値を持つバージョンまたはcharacterEncodingプロパティがあり、他方のツリーにそのようなプロパティがない場合、二つのツリーは等しいとみなされます。

ノードタイプの操作

ツリー内の各ノードにはノードタイプがあります。ノードのnodeTypeプロパティはノードのタイプを返します:

put order's nodeType -- Document
put the nodeType of item 1 of order -- Element

ツリーに存在する可能性があるノードのタイプには、Document、Element、Text、DTD、ProcessingInstruction、Commentがあります。ノードのタイプは変更することができません。ノードが特定のタイプであるかどうかをテストするには、is aオペレーターも使用できます:

put order is a Document -- true

DocumentElementDTDノードだけが子を持つことができます。他のタイプのノードに子ノードを追加しようとするとエラーが発生します。

グローバルプロパティ

以下で説明する関数に加えて、ツリーの動作の一部を管理するために使用できる2つのSenseTalkのグローバルプロパティがあります:

  • The TreeFormat
  • The TreeInputFormat

これらのグローバルプロパティはXMLとツリーのためのグローバルプロパティで定義されています。

ツリー関数

Tree, AsTree関数

挙動:treeまたはasTree関数(as a treeオペレーターによって呼び出される)は、そのパラメーターの値をツリーに変換した値を返します。

構文:
{the} treeFromXML of factor
treeFromXML( expr )
{the} treeFromHTML of factor
treeFromHTML( expr )

tree関数がasTreeプロパティを持つプロパティリスト(オブジェクト)としてパラメータで呼び出された場合、そのプロパティの値が使用されます。 オブジェクトにasTreeExpressionプロパティがある場合、そのプロパティの値が式として評価され(treeFromXML()関数を呼び出すのと同等)、ツリーの値が得られます。 オブジェクトにこれらのプロパティのいずれもない場合、asTree関数メッセージがオブジェクトとそのヘルパーに独占的に送信され、ツリーの値が取得されます。

パラメータがオブジェクトであり、上記の方法で自身のツリー表現を提供しない場合、それはツリー構造またはノードの直接的なプロパティリスト表現とみなされます。 プロパティリストには次の特別なプロパティ(および値)を含めることができます:_tagまたは_element(要素のタグ名); _attributes(要素ノードの属性のプロパティリスト); _children(子ノードのリスト); _text(テキストノードの内容); _commentまたは--(コメントノードの内容); _processingInstructionまたは_pi(処理指示ノードの内容); ?に続く処理指示名(処理指示ノードの本文); _XMLinfo(特別なXML文書属性のプロパティリスト)。 詳細はプロパティリストからツリーを作成するを参照してください。

パラメータがオブジェクトでなく、すでにツリーでない場合、その文字列値はXML式として評価され(treeFromXML()関数を呼び出すのと同等)、ツリーの値が得られます。

パラメータにversionプロパティが含まれている場合、結果のツリーオブジェクトはDocumentタイプのノードになります。それ以外の場合は、Elementノードになります。

例:

put file "configuration.xml" as a tree into config
put asTree("<a>Contents</a>") -- <a>Contents</a>
put { _tag:book, _children:"The Rose" } astree -- <book>The Rose</book>
put tree(_tag:"page", num:8) -- <page num="8"></page>

参考:値の変換 および Expressions.as 演算子

TreeFromXML, TreeFromHTML 関数

振る舞い: treeFromXML 関数はテキスト値を XML として評価し、ツリーを返します。 treeFromHTML 関数はテキスト値を HTML として評価し、その HTML コンテンツのツリー表現を返します。

構文:
{the} documentTreeFromXML of factor
documentTreeFromXML( expr )
{the} documentTreeFromHTML of factor
documentTreeFromHTML( expr )

treeFromXML 関数は、そのパラメータを XML テキストとして評価しようとします。 テキストが有効な XML である場合、それは解析され、結果のツリーが返されます。 テキスト内に XML バージョンなどのドキュメントレベルの情報が存在する場合、返されるツリーはドキュメントノードになります。そうでない場合は、要素ノードになります。 テキストが有効な XML でない場合、返されるツリーは要素やドキュメントではなく XML テキストノードを表し、the result は警告メッセージに設定されます。

同様に、treeFromHTML 関数はそのパラメータを HTML テキストとして評価しようとします。 テキストが有効な HTML(完全なドキュメントではなく有効なフラグメントを含む)である場合、それは解析され、結果のツリーが返されます。 テキストが有効な HTML でない場合、例外がスローされます。

例:

put treeFromXML(xmlText) into aTree
put treeFromHTML(htmlText) into htmlTree

DocumentTreeFromXML, DocumentTreeFromHTML 関数

振る舞い: documentTreeFromXML および documentTreeFromHTML 関数はテキスト値をそれぞれ XML または HTML として評価し、その内容のツリー表現を返します。 戻り値は、エラーがない限り、Element ノードではなく Document ノードになります。

文法:
{the} documentTreeFromXML of factor
documentTreeFromXML( expr )
{the} asTree of factor
asTree( expr )

documentTreeFromXML 関数は、そのパラメータを XML テキストとして評価しようとします。 テキストが有効な XML である場合、それは解析され、結果のツリーが返されます。 テキスト内に XML バージョンなどのドキュメントレベルの情報が存在するかどうかに関わらず、返されるツリーはドキュメントノードになります。 テキストが有効な XML でない場合、返されるツリーはテキストをテキストノードとして含み、the result は警告メッセージに設定されます。

the standardNodeExpressions がオフになっている場合、"as tree" の代わりに "as document tree" を使用して XML をツリーに解析し、そのツリーのノード表現の標準的な動作を確保します。

同様に、documentTreeFromXML 関数はそのパラメータを HTML テキストとして評価しようとします。 テキストが有効な HTML(完全なドキュメントではなく有効なフラグメントを含む)である場合、それは解析され、結果のドキュメントツリーが返されます。 テキストが有効な HTML でない場合、例外がスローされます。

例:

put documentTreeFromXML(xmlText) into docTree
put documentTreeFromHTML(htmlText) into htmlDocTree

STTreeVersion 関数

振る舞い: STTreeVersion 関数は、STTreeNode xmodule の現在のバージョン番号を返します。

構文:
the STTreeVersion
STTreeVersion()

例:

put STTreeVersion()