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
タグで囲みます。この全体のセクションは、customer
と product
の2つの他の要素を含む ドキュメント ノード(上記の例のように)または 要素 ノード(XMLバージョン情報が欠けている場合)を構成します。customer
要素には name
属性 がありますが、追加のコンテンツはありません。 product
要素には code
と size
の属性があり、さらに2つの要素、quantity
と amount
を含みます。 quantity
と amount
の両方の要素には、テキストノード として知られる囲まれたテキストが含まれています。
この情報をツリーで表現すると、次のようになります:
括弧内の情報は、ノードの種類と、そのノードに存在する場合の属性を示しています。ツリー形式では、orderノードが2つの子供(customerとproduct)を持ち、productノードもまた2つの子供(quantityとamount)を持っていることがわかります。quantityとamountノードはそれぞれ一つの子供:対応する値を持つテキストノードを持っています。
XMLデータは主に要素で構成されていることに注意してください(ドキュメントノードは特別な種類の要素として扱うことができます)。各要素にはタグ(order
、customer
、product
などのタグ)、属性(id
、name
、code
などの属性)があり、子供がいるかもしれません。子供たちは要素であるかもしれませんし、単純なテキスト値(3
、23.45
)であるかもしれません。他のノードタイプもありますが、それらはあまり一般的ではなく、この例では示されていません。
ここに示したorderの例は、現在使用されている多くのXMLフォーマットの典型的なものです。要素、属性、テキストをネストした構造に組み合わせることで、XMLは様々なフォーマットと、それらの中のバリエーションを可能にします。
ツリー = リスト + プロパティリスト
SenseTalkがツリーと共に働くアプローチは、ツリーを両方のコンテナタイプのハイブリッドとして扱うことで、リストとプロパティリストを扱うための言語固有の機能を活用しています。ツリーの子供はリストのアイテムのようにアクセスでき、その属性はプロパティリストのプロパティ値のようにアクセスできます。
ツリーについてはいくつかの詳細が異なります(以下で説明しますが)、全体として、リストとプロパティリストの扱いに慣れているなら、ツリーを扱うために必要なことのほとんどをすで に知っています。詳細はListsとProperty 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
上記のコマンドを実行すると、次の結果が得られます:
特別なtext
プロパティは、ツリーやノードのコンテンツだけを抽出するのに役立ちます:
put the text of node "*/product/amount" of order
上記のコマンドを実行すると、次の結果が得られます:23.45
all nodes
またはevery node
を使用して、XPath式に一致するツリーのすべてのノードのリストを返します:
put all nodes "*/product/*" of order
上記のコマンドを実行すると、次の結果が得られます: (
put everynode "*/*/amount" of order
上記のコマンドを実行すると、次の結果が得られます:
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に置き換えられたことを確認します:
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
関数の同じルールを使用してツリーに追加されるときに自動的に変換されます。このセクションの後半で説明されています。Document
、Element
、DTD
のnodeType
を持つノードのみが子を持つことができます。他のタイプのノードには子がいないため、リストのように動作しません。
ツリーをテキストに変換する
ツリーがテキストとしてアクセスされると(put
コマンドで表示されるなど)、SenseTalkはそれを自動的にXML形式のテキスト表現に変換します。the treeFormat's prettyPrint
をtrue
または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
Document
、Element
、DTD
ノードだけが子を持つことができます。他のタイプのノードに子ノードを追加しようとするとエラーが発生します。
グローバルプロパティ
以下で説明する関数に加えて、ツリーの動作の一部を管理するために使用できる2つのSenseTalkのグローバルプロパティがあります:
The TreeFormat
The TreeInputFormat
これらのグローバルプロパティはXMLとツリーのためのグローバルプロパティで定義されています。
ツリー関数
Tree
, AsTree
関数
挙動:tree
またはasTree
関数(as a tree
オペレーターによって呼び出される)は、そのパラメーターの値をツリーに変換した値を返します。
構文:
{the} tree of factor
treeFromXML( expr )
{the} asTree 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} treeFromXML of factor
documentTreeFromXML( expr )
{the} treeFromHTML 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} documentTreeFromHTML 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()