SenseTalkスクリプト内でのXMLとツリー構造の利用
ツリーとノード
ツリーとは、任意の数の子ノードを持つルートノードで構成される階層のことをいいます。各子ノードは、それ自身が任意の深さの子ノードなどを持つツリーである場合があります。各ノード(ルートノードを除く)には親ノードが備わっており、これは子としてそのノードを含むツリー(またはサブツリー)のことをいいます。
各ノードには親ノード1つと0以上の子ノードが含まれることに加えて、タグ名などの様々なプロパティや属性を含む場合もあります。
ツリーの基本構造は以下のようになります。
ツリー内の各ノードは独自の子ノードを持つことができるため、各ノードは(その子とその子孫を併せて)それ自身がツリーとなります。
ツリーと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>
上の例では、最初の行でこれがXMLドキュメントのバージョン1.0であることが示されます。2行目と最後の行のorderタグで残りのコンテンツが囲まれています。本セクションは全体として、(上に示した例のような)ドキュメントノード、またはその他2つの要素(customerとproduct)を含む要素ノード(XMLのバージョン情報が存在しない場合)のいずれかで構成されます。customer要素はname属性を含みますが、その他のコンテンツは含みません。product要素はcodeとsize属性を含み、さらに2つの要素(quantityとamount)も含みます。quantityとamountのどちらの要素も、テキストノードとして知られる囲まれたテキストを含みます。
ツリー内の情報は、以下のように表すことができます。
丸括弧内の情報は、そのノード内に存在するノードの種類と属性(存在する場合)を表します。ツリー形状において、orderノードに2つの子(customerとproduct)が存在し、そのproductノードにも2つの子(quantityとamount)が存在することが確認できます。quantityノードとamountノードにはそれぞれ、子(対応する値を保持するテキストノード)が1つ存在します。
なお、XMLデータは主に要素で構成されることに留意してください(ドキュメントノードは特殊なタイプの要素として処理できます)。各要素はタグ(order、customer、productなど)を含み、属性(id、name、codeなど)や子を含む場合もあります。要素の子は、要素またはシンプルなテキスト値(3、23.45)である場合があります。処理命令ノードやコメントノードなどのその他の種類のノードも存在しますが、これらはあまり一般的ではなく、本例では提示しません。
ここに示したorderの例は、今日使用されている多くのXMLフォーマットの一般的な例です。要素や属性、テキストをネスト化された構造内で組み合わせることにより、XMLでは幅広い多様なフォーマットやそのバリエーションを実現できます。
ツリー=リスト+プロパティリスト
ツリーを操作するためのSenseTalkのアプローチでは、ツリーをリストとプロパティリストの2つのコンテナタイプのハイブリッドとして扱うことで、リストとプロパティリストの処理言語に固有の機能を活用します。ツリーの子には、リスト内のアイテムと全く同じようにアクセスでき、その属性には、プロパティリスト内のプロパティ値と同じようにアクセスできます。
以下で説明するように、ツリーによって一部の詳細は異なりますが、全体として、リストとプロパティリストの扱いに熟知している場合は、ツリーの扱いについても既に大部分のことを知っていると言えます。詳細は、リストとプロパティリストを参照してください。
ツリーはこうした特性を有するため、XMLとは関係のない状況でも、リストとプロパティリストの両方として振る舞うハイブリッドタイプのコンテナとして役に立つ場合があります。
ツリーの扱い
XMLからツリーを作成する
XMLデータを含むURLのコンテンツをスクリプト内の内部ツリー構造にロードする場合は、as a tree演算子を使用します。
put url "http://some.site/data.xml" as a tree into myTree
本ステートメントは指定したURLにアクセスし、そのコンテンツを読み取ります。as a tree演算子は、データをXMLドキュメントとして処理し、ツリー構造に変換して変数myTreeに格納するようにSenseTalkに命令します。
状況に応じて、スクリプトに直接組み込まれた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>
}}
set order to XMLSource as tree
以下に示す別の例では、このorderツリーの参照が存在します。
ツリーからXMLを作成する
ツリー内のデータからXMLフォーマットのテキストを作成することは、XMLテキストからツリーを作成するよりもさらに簡単です。ツリー構造をテキストとして使用する場合は、常にツリーコンテンツのXML表現が自動的に作成されます。そのため、ツリーからXMLファイルを作成するのに必要なのは、例えば以下のようなシンプルなコマンドになります。
put myTree into file "/path/to/aFile.xml"
ツリーコンテンツへのアクセス
ツリーの子には、リストのアイテムと同じようにアクセスできます。
put item 1 of order
上記のコマンドを実行すると、次の結果が得られます。<customer name="Janet Brown"></customer>
ツリーの属性には、プロパティリストのプロパティと同じようにアクセスできます。
put order.id
上記のコマンドを実行すると、次の結果が得られます。001
アイテムとプロパティを組み合わせると、より深くネスト化されたデータにアクセスできます。
put the code of item 2 of order
上記のコマンドを実行すると、次の結果が得られます。prod345
XPath式の使用によるツリーノードへのアクセス
XPathは、XMLドキュメントのコンテンツにアクセスするための標準メカニズムです。これにより、関心のあるノードやノードの組を描写する方法が提供され、必要とする情報を引き出すことができます。SenseTalkはnode式を通してこの力強いメカニズムをサポートしており、ツリー内のコンテンツにタグ名を用いてアクセスできます。
put node "*/customer" of order
上記のコマンドを実行すると、次の結果が得られます。<customer name="Janet Brown"></customer>
ノード式を用いて、ネスト化されたツリーノードのパスを描写できます。
put node "*/product/amount" of order
上記のコマンドを実行すると、次の結果が得られます。<amount>23.45</amount>
特殊なtextプロパティを利用して、ツリーまたはノードのコンテンツを抽出できます。
put the text of node "*/product/amount" of order
上記のコマンドを実行すると、次の結果が得られます。23.45
XPath式と一致するツリーの各ノードのリストを返すには、all nodesまたはevery nodeを使用します。
put all nodes "*/product/*" of order
上記のコマンドを実行すると、次の結果が得られます。
(<quantity>3</quantity>,<amount>23.45</amount>)
put every node "*/*/amount" of order
上記のコマンドを実行すると、次の結果が得られます。(<amount>23.45</amount>)
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に置き換わったことを確認するには、次の出力を検索します。<amount>7</amount>
XPath式には、特定のノードにアクセスするための様々なオプションが存在しますが、ここに示すのはそのごく一部です。XPathの使用に関する詳細情報は、XPath の定義またはXML Path Language(XPath)の全仕様を参照してください。
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
次の結果を検索します。(<customer name="Janet Brown"></customer>,<customer name="Jane Doe"></customer>)
子はツリーまたはツリーに変換可能な値である必要があります。本セクションの後半で説明するように、値はtree関数と同じルールを使用して、ツリーに追加する際に自動的に変換されます。Document、ElementまたはDTDのnodeTypeを持つノードのみが子を持つことができます。その他のタイプのノードは子を持たず、リストのように振る舞うことはできません。
ツリーのテキストへの変換
ツリーにテキストとしてアクセスする場合(putコマンドで表示される場合など)は、SenseTalkが自動的にXMLフォーマットのテキスト表現に変換します。treeFormat's prettyPrintをtrueまたはfalseに設定することで、XMLをより読みやすくするために複数行で字下げ設定するかどうかを管理できます。デフォルトでは、本プロパティはtrueに設定されます。standardFormat()関数は、ツリーをテキストとしてフォーマットするのにも使用できます。
ツリーにドキュメントレベルの情報(_xmlinfoプロパティによって定義される)が含まれる場合は、その情報がツリーのテキスト表現の生成時に使用されます。_xmlinfoプロパティは、(サブツリーではなく)ツリーの最上位レベルのみで設定できるため、別のサブツリーとしてツリーを挿入すると、そのドキュメントレベルの情報が破棄されます。_xmlinfoプロパティは、以下のドキュメントレベルのプロパティを組み込むことのできるプロパティリストです。
- CharacterEncoding:設定する場合は、本プロパティを有効なXMLエンコーディングの名前とする必要があります(有効なエンコーディングの名前のリストについては、文字設定(IANA)を参照してください。これはSenseTalkの文字列のエンコーディングタイプとは異なります)。
- DocumentContentType:XML、XHTML、HTML、Textのいずれかとする必要があります。本プロパティは、そのツリーに対して生成されるテキスト表現のいくつかの側面を管理します。
- MIMEType:有効なMIMEタイプに設定する必要があります(メディアタイプ(IANA)を参照)。
- URI:そのドキュメントと関連するUniform Resource Identifier(通常はURL)。
- Version:XMLバージョンを示す1.0か1.1のいずれかである必要があります。
また、_xmlinfoは、ドキュメントのルート要素の前後でコメントまたは処理命令を表現する、ツリーノードの2つのリストを組み込むことができます。
- 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
--
一部のXMLフォーマットはコンテンツではなく属性を使用し、以下のように実行できます。
put tree(_tag:"pg",_attributes:(id:43)) -- <pg id="43"></pg>
この場合は、簡略化されたフォーマットも使用できます。
put tree(_tag:"pg", id:43)-- <pg id="43"></pg>
プロパティリストをツリーに変換する際のルールは、次のように要約できます。プロパティが1つしか存在せず、かつスペシャルプロパティでもない場合は、そのプロパティ名は要素名とみなされ、その値は要素の子を表します。プロパティリストに_tagまたは_elementプロパティが含まれる場合は、要素ノードが生成されます。このケースで_attributesプロパティが存在しない場合は、特別な意味を持たないその他のプロパティが属性であると仮定されます。
リストからツリーを作成する
tree関数(またはasTree()またはas a tree演算子)を利用して、リストをツリーに変換することもできます。この方法で変換する場合は、リストは名前のない(emptyタグが付いた)ツリーとなります。これは、変換対象のネスト化されたリストまたはプロパティリスト内のリストにも適用されます。
ツリーをプロパティリストに変換する
ツリーは、as演算子を使用してプロパティリストにも変換できます。例:
put "<zip>80521</zip>" as tree as object -- (zip:(80521))
SenseTalkは、可能な場合はプロパティリスト向けに簡略化された形式を使用します。すべてのケースで標準フォーマットを生成するには、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演算子または=演算子を使用して)2つの値が等しいかどうか比較する場合は、通常、テキストとして比較されます。2つの値が(プロパティリストやツリーのXMLテキスト表現ではなく、ツリーフォーマットの)ツリーの場合に限り、ツリーとして比較されます。ツリー以外の値に対してas treeを指定することで、ツリーとして比較することができます。
ツリーを別のツリーと比較する場合は、これら2つのツリーは、同じコンテンツ(同じ子やプロパティなど)を持っている場合に等しいとみなされます。ただし、2つのツリーがほぼ同一で、違いは一方のツリーがデフォルト値とともにバージョンプロパティやcharacterEncodingプロパティを持ち、もう一方のツリーがこのようなプロパティを持たないことである場合は、これら2つのツリーは等しいとみなされます。
ノードタイプの扱い
ツリー内の各ノードには、ノードタイプが存在します。ノードのnodeTypeプロパティは、ノードのタイプを返します。
put order's nodeType -- ドキュメント
put the nodeType of item 1 of order -- 要素
ツリー内に存在するノードのタイプには、ドキュメント、要素、テキスト、DTD、処理命令、コメントなどがあります。ノードのタイプを変更することはできません。ノードが特定のタイプかどうかを検証するのに、is a演算子を使用することもできます。
put order is a Document -- true
ドキュメント、要素、およびDTDノードのみが子を持つことができます。これらのタイプ以外のノードに子ノードを追加しようとすると、エラーが生じます。
グローバルプロパティ
以下で説明する関数のほかに、次の2つのSenseTalkグローバルプロパティを使用して、ツリーの挙動における特定の側面を管理することができます。
これらのグローバルプロパティは、XMLとツリーのグローバルプロパティで定義されます。
Tree関数
tree、asTree関数
振る舞い
(as a tree演算子によって呼び出される)treeまたはasTree関数は、ツリーに変換されるパラメータ値を返します。
例
put file "configuration.xml" as a tree into config
put asTree("<a>Contents</a>") -- <a>Contents</a>
put ( _tag:book, _children:"The Rose" ) as tree -- <book>The Rose</book>
put tree(_tag:"page", num:8) -- <page num="8"></page>
技術トピック |
構文: {the} tree of factor tree(expr) {the} asTree of factor asTree(expr) |
asTreeプロパティを含むプロパティリスト(オブジェクト)のパラメータを用いてtree関数を呼び出す場合は、そのプロパティの値が使用されます。オブジェクトにasTreeExpressionプロパティが含まれる場合は、そのプロパティの値は、ツリー値を入手するために式(treeFromXML()関数の呼び出しに相当)として評価されます。オブジェクトがこのようなプロパティを全く含まない場合は、ツリー値を入手するためにasTree関数メッセージがオブジェクトとそのヘルパーのみに送信されます。 |
パラメータがオブジェクトであるものの、上述した何らかの方法でそれ自身のツリー表現が示されない場合は、それがツリー構造またはノードの直接的なプロパティリスト表現であるとみなされます。プロパティリストに含まれる可能性のある特別なプロパティ(および値)には、次のものがあります。_tag または_element(要素のタグ名)、_attributes(要素ノードの属性のプロパティリスト)、_children(子ノードのリスト)、_text(テキストノードのコンテンツ)、_commentまたは--(コメントノードのコンテンツ)、_processingInstructionまたは_pi(処理命令ノードのコンテンツ)、? 処理命令の名前が後に続く(処理命令ノードのボディ)、_XMLinfo(特別なXMLドキュメントの属性のプロパティリスト)。詳細情報は、プロパティリストからのツリーの作成を参照してください。 |
パラメータがオブジェクトでもツリーでもない場合は、その文字列値は、ツリー値を入手するためにXML式(treeFromXML()関数の呼び出しに相当)として評価されます。 |
パラメータにバージョンプロパティが含まれる場合は、結果のツリーオブジェクトはドキュメントタイプノードとなり、それ以外の場合は要素ノードとなります。 |
次の項目も参照してください。値の変換および式におけるas演算子。
treeFromXML、treeFromHTML関数
振る舞い
treeFromXML関数は、テキスト値をXMLとして評価し、ツリーを返します。treeFromHTML関数は、テキスト値をHTMLとして評価し、そのHTMLコンテンツのツリー表現を返します。
例
put treeFromXML(xmlText) into aTree
put treeFromHTML(htmlText) into htmlTree
技術トピック |
構文:{the} treeFromXML of factor treeFromXML(expr) treeFromXML(expr) {the} treeFromHTML of factor treeFromHTML(expr) |
treeFromXML関数は、そのパラメータをXMLテキストとして評価しようとします。テキストが有効なXMLである場合は解析され、結果のツリーが返されます。返されるツリーは、XMLバージョンなどのドキュメントレベルの情報がテキストに含まれる場合はドキュメントノード、そうでない場合は要素ノードとなります。テキストが有効なXMLでない場合は、返されるツリーは要素でもドキュメントでもなく、XMLテキストノードを表し、the resultが警告メッセージに設定されます。 |
同様に、treeFromHTML関数は、そのパラメータをHTMLテキストとして評価しようとします。テキストが(フルドキュメントではなく)有効なフラグメントなどの有効なHTMLである場合は解析され、結果のツリーが返されます。テキストが有効なHTMLではない場合は、例外が投げられます。 |
documentTreeFromXML、documentTreeFromHTML関数
振る舞い
documentTreeFromXML関数とdocumentTreeFromHTML関数は、テキスト値をXMLまたはHTMLとしてそれぞれ評価し、そのコンテンツのツリー表現を返します。返される値は、要素ノードではなく、常にドキュメントノードとなります(エラーが存在しないと仮定する場合)。
例
put documentTreeFromXML(xmlText) into docTree
put documentTreeFromHTML(htmlText) into htmlDocTree
技術トピック |
構文: {the} documentTreeFromXML of factor documentTreeFromXML(expr) {the} documentTreeFromHTML of factor documentTreeFromHTML(expr) |
documentTreeFromXML関数は、そのパラメータをXMLテキストとして評価しようとします。テキストが有効なXMLである場合は解析され、結果のツリーが返されます。返されるツリーは、XMLバージョンなどのドキュメントレベルの情報がテキストに存在するかどうかに関わらず、ドキュメントノードとなります。テキストが有効なXMLでない場合は、返されるツリーにはテキストノードとしてテキストが組み込まれ、the resultが警告メッセージに設定されます。 |
同様に、documentTreeFromXML関数は、そのパラメータをHTMLテキストとして評価しようとします。テキストが(フルドキュメントではなく)有効なフラグメントなどの有効なHTMLである場合は解析され、結果のドキュメントツリーが返されます。テキストが有効なHTMLではない場合は、例外が投げられます。 |
STTreeVersion関数
振る舞い
STTreeVersion関数は、STTreeNode xmoduleの現在のバージョン番号を返します。
例
put STTreeVersion()
技術トピック |
構文:the STTreeVersion STTreeVersion() |