タグ別アーカイブ: XSLT

XSLTを学ぶ (11)論理値(Boolean)と関連する基本的な関数のいくつか

第9回[1]では、式の生成規則を辿っている途中に幾つかわからない項目が出てきました。その一つは、ノード集合に対する演算の扱いです。ここでは論理演算や比較の演算におけるノード集合の扱いを調べてみます。

論理値(Booleans)[2]

or式は左辺と右辺の両方のオペランドをboolean関数と同じように論理値に変換して評価します。どちらかが真であれば真となり、そうでないとき偽となります。boolean関数はXPathで規定するコア関数の一種であり、引数を論理値に変換します。ノード集合は空でないとき真となります(詳しくは下に紹介しました)。

and式は両方のオペランドをboolean関数と同じように論理値に変換して評価します。両方が真であれば真となります。そうでないとき偽となります。

第9回の規則[23]の関係式(RelationalExpr)すなわち <=、<、>=、>、および等価式(EqualityExpr)すなわち=または!=、は左辺と右辺の二つのオペランドを次のように比較します。(ノード集合が関係するときだけを取り上げてみます。)

ノード集合同士を比較するときは、最初のノード集合と二つ目のノード集合の中に、ノードの文字列値同士を比較したときに真になるようなノードが含まれている時に限り、その比較は真になります。

ノード集合と数値の比較では、ノードの文字列値をnumber関数で数値に変換し、数値同士として比較します。ノード集合の中に、数値同士を比較して真になるようなノードが含まれていれば、比較が真になります。

ノード集合と文字列値の比較では、ノードの文字列値と他方の文字列値を比較し、文字列値同士を比較して真になるようなノードが含まれていれば、比較が真になります。

ノード集合と論理値の比較では、ノード集合をboolean関数で論理値にして、他方の論理値と比較します。

XPathには基本的な関数が規定されています。次に今日出てきた関数を紹介します。

boolean関数[3]
形式: boolean boolean(object)

boolean関数は引数を次のように論理値に変換します。
・数値は、ポジティブゼロでもネガティブゼロでもなく、NaN(Not-a-Number:数値でない)でもないとき真となります。
・ノード集合は空でないとき真となります。
・文字列は、長さがゼロでないとき真となります。
・四つの基本型以外のオブジェクトはその型依存の方法で論理値に変換されます。

number関数[4]
形式: number number(object?)

number関数は引数を次のように論理値に変換します。
・数値の後が空白で、前にオプションのマイナス記号、さらにその前のオプションの空白から構成される文字列は、その文字列によって表現される数学的値に最も近いIEEE 754数に変換されます。それ以外の文字列はNaNに変換されます。
・論理値の真は1に変換され、論理値の偽は0に変換されます。
・ノード集合は最初にstring関数を使ったように文字列に変換され、次いで引数が文字列のときと同様に数値に変換されます。
・四つの基本型以外のオブジェクトはその型依存の方法で数値に変換されます。

もし、引数が省略されたときは、既定値として文脈ノードのみから成るノード集合が使われます。

string関数[5]
形式: string string(object?)

文字列関数はオブジェクトを次のように文字列に変換します。
・ノード集合はノード集合の中で文書順で最初のノードの文字列値を返すことで文字列値に変換されます。ノード集合が空のときは空文字列が返されます。
・数値は次のように文字列に変換されます。
 ・NaNは文字列NaNに変換されます。
 ・ポジティブゼロは文字列0に変換されます。
 ・ネガティブゼロは文字列0に変換されます。
 ・ポジティブな無限大は文字列Infinityに変換されます。
 ・ネガティブな無限大は文字列-Infinityに変換されます。
 ・数値が整数型のときは、小数点や先行するゼロのない十進数で表現されます。数値がマイナスのときは、マイナス記号が先行します。
 ・整数でないときは、小数点を含み、小数点の前に少なくとも1個の十進数があり、小数点の後に少なくとも1個の十進数があり、マイナスのときは、マイナス記号が先行する形式となります。不要な先行するゼロがあってはならず、少数点の後には他のIEEE 754と区別するのに必要なだけの数値がなければなりません。
・論理値の偽は文字列falseになり、論理値の真は文字列trueになります。
・四つの基本型以外のオブジェクトはその型依存の方法で文字列に変換されます。

もし、引数が省略されたときは、既定値として文脈ノードのみから成るノード集合が使われます。

なお、string 関数は表示用に整形するために用意されているものではありません。整形にはXSLTのxsl:number要素を使います。

[1] XSLTを学ぶ(9)ステップの文法を追求する-述部(Predicates)と式
[2] 3.4 Booleans
[3] boolean関数
[4] number関数
[5] string関数

前回:
XSLTを学ぶ(10)式によるノード集合の作成、ノード集合の和集合、フィルター式

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ(9) ステップの文法を追求する-述部(Predicates)と式

第3回[1]からパスの文法を調べてきました。パスの重要な構成要素にステップがあり、ステップ(省略)は軸、ノードテスト、述部(オプションなので必須ではない)から構成されることを調べました。

ステップの最後の構成部品はオプションの述部です。第6回[2]で見ましたが、述部はを[]で囲った形式です。

式とはどんなものでしょうか? まず、XPathの式の生成規則[3]をトップから辿ってみます。

スタートは定義の[14]ですが、式Exprとは、OrExprです。[21]orExprはAndExprを’or’でつなげたものです。そして、[22]AndExprとは、EqualityExprを’and’でつなげたものです。[23]EqualityExprは、RelationalExprを’=’でつなげたものまたは’!=’でつなげたもの。[24]RelationalExprは、AdditiveExprを'<‘ ‘>”<=’ ‘>=’でつなげたもののようです。つまり、このあたりまでは、式はAdditiveExpr(加算式)の論理演算ということになります。

[14] Expr ::= OrExpr
[21] OrExpr ::= AndExpr | OrExpr ‘or’ AndExpr
[22] AndExpr ::= EqualityExpr | AndExpr ‘and’ EqualityExpr
[23] EqualityExpr ::= RelationalExpr
| EqualityExpr ‘=’ RelationalExpr
| EqualityExpr ‘!=’ RelationalExpr
[24] RelationalExpr ::= AdditiveExpr
| RelationalExpr ‘<‘ AdditiveExpr | RelationalExpr ‘>’ AdditiveExpr
| RelationalExpr ‘<=’ AdditiveExpr | RelationalExpr ‘>=’ AdditiveExpr

ということで、さらにAdditiveExprとは何かを見てみます。[25]ではAdditiveExprは、MultiplicativeExprを’+’または’-‘でつなげたものです。

[25] AdditiveExpr ::= MultiplicativeExpr
| AdditiveExpr ‘+’ MultiplicativeExpr
| AdditiveExpr ‘-‘ MultiplicativeExpr

[26]ではMultiplicativeExprとは、UnaryExpr(単項式)、またはMultiplicativeExprにUnaryExprを掛けた(’*’)、またはMultiplicativeExprをUnaryExprで割り算(’div’)、剰余算(’mod’)したものです。
[26] MultiplicativeExpr ::= UnaryExpr
| MultiplicativeExpr MultiplyOperator UnaryExpr
| MultiplicativeExpr ‘div’ UnaryExpr
| MultiplicativeExpr ‘mod’ UnaryExpr
[34] MultiplyOperator ::= ‘*’

UnaryExprは、UnionExprまたはその前にマイナス記号(’-‘)をつけたもの。

[27] UnaryExpr ::= UnionExpr | ‘-‘ UnaryExpr

UnionExprは、ひとつのPathExpr(パス式)、またはそれを’|’で結合したものです。

[18] UnionExpr ::= PathExpr| UnionExpr ‘|’ PathExpr

PathExpr式は、LocationPath(ロケーションパス)、またはFilterExprまたは、FilterExprと相対ロケーションパスを’/’、’//’ で結合したものです。

[19] PathExpr ::= LocationPath
| FilterExpr
| FilterExpr ‘/’ RelativeLocationPath
| FilterExpr ‘//’ RelativeLocationPath

ロケーションパスについては第3回[2]ですでに学びましたが、XMLツリーのノードを選択するものです。ノードの選択結果はノードの集まり(ノード集合)ですが、これに対して、掛け算(’*’)、割り算(’div’)、剰余算(’mod’)、足し算(’+’)、引き算(’-‘)、比較などの演算をするのは少し不思議な気もします。これは後ほど調べてみることにします([5])。

FilterExprの方は、PrimaryExprまたはPrimaryExprに述部(Predicate)を付けたものとなります。ここに出てくる述部はFilterExpr Predicateのように使われますが、ステップの中で出てくる述部の使われ方はAxisSpecifier NodeTest Predicate*です。この2種類の述部の使われ方の違いはなんでしょうか? これも後ほど調べてみましょう([4])。

PrimaryExprは、VariableReference(変数参照)、式を()で囲ったもの、リテラル、数値、FunctionCall(関数呼び出し)のどれかです。ですので、式には数置の四則演算も表現したものも含まれます(よく知っている初歩的な数式も含まれるということで一安心です)。

[20] FilterExpr ::= PrimaryExpr
| FilterExpr Predicate
[15] PrimaryExpr ::= VariableReference
| ‘(‘ Expr ‘)’
| Literal
| Number
| FunctionCall

最も単純なケースでは、一つの数値(Number)だけでも式となります。例えば、次のように下から辿ってみます。
(1) PrimaryExprがNumber:100
(2) FilterExprがPrimaryExpr:100
(3) PathExprがFilterExpr:100
(4) UnionExprがPathExpr:100
(5) UnaryExprがUnionExpr :100
(6) MultiplicativeExprがUnaryExpr:100
(7) AdditiveExprがMultiplicativeExpr:100
(8) RelationalExprがAdditiveExpr :100
(9) EqualityExprがRelationalExpr :100
(10) AndExprがEqualityExpr:100
(11) OrExprがAndExpr:100
(12) ExprがOrExpr:100

ということで、述部に[100]と書くことができます。

まとめますと、述部([]内)にはを書きますが、式としてはロケーションパスを書くこともできますし、また、数値、変数、関数呼び出し、数式を書くこともできる、ということになります。

途中で、いろいろわからない言葉が出てきていますので、次回以降、もう少し詳しく調べてみます。

[1] XSLTを学ぶ (3) パスとは
[2] XSLTを学ぶ (6) ステップの文法を追求するの[8]、[9]式
[3] 3 Expressions
[4] 次回(第10回)のpreceding::foo[1] と(preceding::foo)[1]の比較 の項を参照してください。
[5] ノード集合の論理演算、比較演算については第11回を参照してください。

【広告】★AH Formatter XML関連出版物の紹介

次回:
XSLTを学ぶ (10)式によるノード集合の作成、ノード集合の和集合、フィルター式

前回:
XSLTを学ぶ(8)ステップの文法を追求する-NodeTest

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ (8) ステップの文法を追求する-NodeTest

前回は軸について調べましたので、今回はNodeTestを調べてみます。XPath仕様では、NodeTestを次のように規定しています[1]

[7] NodeTest ::= NameTest | NodeType ‘(‘ ‘)’ | ‘processing-instruction’ ‘(‘ Literal ‘)’
[37] NameTest ::= ‘*’ | NCName ‘:’ ‘*’ |QName
[38] NodeType ::= ‘comment’|’text’|’processing-instruction’|’node’

まず主ノードタイプを次のように定義します。ステップの文法では軸の指定に続いてNodeTestを記述します。NodeTestでは軸毎に主ノードタイプに該当するノードを選択することになります。

・attribute軸の主ノードタイプは属性
・namespace軸の主ノードタイプは名前空間
・その他の軸の主ノードタイプは要素

文法上は、attribute::text()のような組み合わせができますが、これは無意味なので何も選択しません。

(1) NameTest

NameTestでは要素や属性の名前を指定して一致するものを選択します。

NameTestでは’*’を使えます。’*’は主ノードタイプが何であれすべてのノードに対して真となります。但し、NameTestの前には、軸指定子(AxisSpecifier)が置かれます。軸指定子が省略されないときは、例えば、child::* は起点ノードの子供であるすべての要素ノードを選択します。attribute::*は起点ノードのすべての属性を選択します。

ステップでは軸指定子を省略できます。するとステップは*または@*の形式となります。ステップにおいて*を指定するとchild::*であり、@*とするとAttribute::*です(第6回[3]の[5]と[13]の規定による)。

二番目のNCNameは、名前空間の接頭辞です。接頭辞はXML名前空間の仕様で規定されています[2]

xmlns:svg=”http://www.w3.org/2000/svg”

という名前空間の宣言があるとしますと、NCNameは’svg’にあたります。svg:*はsvg名前区間にあるすべてのノードを選択し、child::svg:*は文脈ノードの子供でsvg名前空間に属する要素ノードをすべて選択します。

QNameは名前空間接頭辞(オプション)で修飾された名前です。

(2) NodeType ‘(‘ ‘)’

NodeTestは、ノードの種類でノードを選択することもできます。ノードの種類は次の4種類です。

comment()
text()
processing-instruction()
node()

例えば、child::text()は起点ノードの子供のテキストノードを選択します。
comment()はコメントノード、processing-instruction()は処理命令のノードを選択します。
node()は任意の種類のノードを選択します。

ステップで、node()と記述すると、軸を省略したことになり、child::node()を意味します。従って、要素ノードのみを選択します。

[1] 2.3 Node Tests
[2] 3 Declaring Namespaces
[3] XSLTを学ぶ(6)ステップの文法を追求する

【広告】★AH Formatter XML関連出版物の紹介

次回:
XSLTを学ぶ(9) ステップの文法を追求する-述部(Predicates)と式

前回:
XSLTを学ぶ(7)ステップの文法を追求する-軸とは

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ (7) ステップの文法を追求する-軸とは

パスは、ステップを’/’オペレータで結合したものであること、そしてステップは、AxisSpecifier NodeTest Predicate*の形式または省略形で記述されることを前回まで[1]に学びました。

ステップの例として、child::para[position()=1]を取り上げてみます。child::が軸指定子(AxisSpecifier)であり、あるノードを起点とするとき、その起点ノードの子供を選択します[2]

その後のparaがNodeTestでノードの名前の指定であり、child::paraは、起点ノードの子供で名前がparaのノードを選択します。NodeTestには’*’を使うこともでき、child::*とすると起点ノードの子供であるノードをすべて選択します。

[position()=1]はオプションの述部(Predicate)です。この場合、述部はノード集合の中での最初のノードを選択します。

軸は起点のノードからXML文書のツリーの方向を指定します。第1回[3]で学びましたが、ノードには7種類があり、また、軸の名前にはancestor、ancestor-or-self、attribute、child、descendant、descendant-or-self、following、following-sibling、namespace、parent、preceding、preceding-sibling、selfの13種類があります。

この中でself軸は起点となるノード自身を含みます。起点ノードが要素ノードのとき、self、ancestor、descendant、following、precedingは一つのXML文書の(属性、名前空間を除外して)すべてのノードを網羅します。

例えば、次のようなXML文書を考えてみます。

<!–?xml version=”1.0″?–>
<doc>
<body>
<p s=”man1″>Hello! How are you?</p>
<p s=”man2″><img src=”pic1″/>I am fine, thank you.<img src=”pic2″/></p>
<p s=”man3″>I am fine, thank you.</p>
</body>
</doc>

このXML文書をノードのツリーで表します。仮に起点が二つ目の要素ノードpであるとします。このときself::はpノードです。そこを起点にしてancestor、descendant、following、precedingは次のような関係になります。

XSLT2

上の図では、selfの子供pの属性ノード(src=”pic1″など)は除外しています。第2回[4]で説明しましたように属性ノードは子供(child)にはなりません。XSLT仕様では、decendentは、「childまたはchildの子供である」とされています。従って、属性や(名前空間ノードも)decendentにはなりません[5]

また、属性や(名前空間ノードも)はprecedenig、followingからも除外されています。

上の図とは異なりますが、もし、属性ノードsrc=”pic1″がselfであった時は、ancestorはその親であるpノードからルートノードまでとなります[6]。しかし、 following-sibling、preceding-siblingは空です。

child、parentについては第2回[4]で説明しました。child軸、parent軸はそれぞれselfノードの子または親です。child軸は複数の子供ノードを含みます。parent軸はあるとしてもひとつの親ノードのみを含みます。

attribute軸、namespace軸はそれぞれselfの属性ノード、名前空間ノードを含みます。

[1] XSLTを学ぶ(3)パスとは
XSLTを学ぶ(6)ステップの文法を追求する
[2] XPathでは起点ノードを文脈ノードといいます。そして、以下の説明の起点ノードのところは文脈ノードになっています。
[3] XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う
[4] XSLTを学ぶ(2)ノードツリーとノードの親子、子孫関係
[5] 2.2 Axes
[6] XPathの仕様の2.2 Axesには、文脈ノードのancestorは、文脈ノードの親(parent)と親の親、以下同じ、から成るとあります。そして、5.3 Attribute Nodesには、要素はそれに付随する属性ノードの親である、と書いてあります。従って、属性ノードのancestorにはその親である要素ノードを選択することになります。

【広告】

次回:
XSLTを学ぶ(8)ステップの文法を追求する-NodeTest

前回:
XSLTを学ぶ(6)ステップの文法を追求する

★AH Formatter XML関連出版物の紹介

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ (6) ステップの文法を追求する

第3回([1])と前回([2])でパスには「式の構成部品としてのパス」(ロケーションパス)と「パターンの記述のためのパス」(パターンパス)の2種類あること、そしてロケーションパスは式の一部でありxsl:要素のselect属性で使われること。パターンパスは、match属性で使われることを説明しました。

パスを構成する文法を調べると、ステップがその基本的な単位になっています。パスはステップを’/’で結合して構成します。

そこで、ステップについてもう少し詳しく調べてみます。

1. ロケーションパスのステップは、XPath仕様[3]で決まっています。第3回でステップの文法の入り口として、次の項を紹介しました。

[4] Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep

ステップは軸の指定子(AxisSpecifier)とノードテスト(NodeTest)とオプション(*)の述部(Predicate)、または、省略形(AbbreviatedStep)から構成します。

ステップの省略形は ‘.’(自分自身、self::node()の省略形)、または’..’(親、parent::node()の省略形)です。

[12] AbbreviatedStep ::= ‘.’ | ‘..’

軸の指定子の定義は、次のようになっています。

[5] AxisSpecifier ::= AxisName ‘::’ | AbbreviatedAxisSpecifier
[6] AxisName ::= ‘ancestor’ | ‘ancestor-or-self’ | ‘attribute’ | ‘child’ | ‘descendant’ | ‘descendant-or-self’ | ‘following’ | ‘following-sibling’ | ‘namespace’ | ‘parent’ | ‘preceding’ | ‘preceding-sibling’ | ‘self’

軸の指定子は、軸の名前(AxisName)と’::’または省略形の軸指定子(AbbreviatedAxisSpecifier)で、軸の名前は’ancestor’から’self’まで13種類あります。

[13] AbbreviatedAxisSpecifier ::= ‘@’?

省略形の軸指定子はなにも指定しないか’@’です。なにも指定しないとデフォルトはchild::です。
@はattribute::の省略形です。その他、’//’は/descendant-or-self::node()/の省略形とされています(規則[11]省略)。

NodeTest以下は次のようになっていますが、次回以降もう少し詳しく調べてみます。

[7] NodeTest ::= NameTest | NodeType ‘(‘ ‘)’ | ‘processing-instruction’ ‘(‘ Literal ‘)’
[37] NameTest ::= ‘*’ | NCName ‘:’ ‘*’ | QName  
[38] NodeType ::= ‘comment’ | ‘text’ | ‘processing-instruction’ | ‘node’

NCName、QNameはXML名前空間([4])で規定されています。

[8] Predicate ::= ‘[‘ PredicateExpr ‘]’
[9] PredicateExpr ::= Expr 

述部は式(Expr)を'[‘ ‘]’で囲ったものです。

2. パターンの構成要素であるステップ(ステップパターン)は、XSLT仕様([5])で決まっています。その文法は次の通りです。

[5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate*
[6] ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier
| (‘child’ | ‘attribute’) ‘::’

NodeTest、Predicate、AbbreviatedAxisSpecifierはXPathのステップを参照しています。XSLT仕様はXPath仕様を利用して作られていることがよく分かります。

[1] XSLTを学ぶ(3)パスとは
[2] XSLTを学ぶ(5)パターンの記述のためのパス
[3] XML Path Language (XPath) Version 1.0
[4] Namespaces in XML 1.0 (Third Edition)
[5] XSL Transformations (XSLT) Version 1.0
[6] 『スタイルシート開発の基礎』

【広告】★AH Formatter XML関連出版物の紹介

次回:
XSLTを学ぶ(7)ステップの文法を追求する-軸とは

前回:
XSLTを学ぶ(5)パターンの記述のためのパス

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ (5) パターンの記述のためのパス

前回[1]は、「式の構成部品としてのパス」を調べてみました。これはXPath仕様[2]で規定されているものです。

もう一つは、「パターンの記述のためのパス」があります。こちらはXSLT仕様[3]で規定されています。本書(『スタイルシート開発の基礎』[4])では、パターンについては、3.7.1 パタン(p.33)で触れています。しかし、パスの役割についてはあまり詳しく記述されていませんので、仕様書で少し詳しく調べてみます。

式は主にselectの属性の値として設定します。XSLT V1.0ではselect属性は次の要素に定義されています。

xsl:variable
xsl:param
xsl:apply-templates (ノード集合式のみ)
xsl:value-of (文字列式のみ)
xsl:with-param
xsl:sort (文字列式のみ)
xsl:copy-of
xsl:if(論理式のみ)
xsl:when(論理式のみ)
xsl:for-each(ノード集合式のみ)

パターンは、スタイルシート規則(xsl:template)のmatch属性の値として規定されています。これを含めてmatch属性が使えるのは次の三つの要素です。

xsl:template
xsl:key
xsl:number

XSLTのxsl:templateの説明の項(5 Template Rules)にはパターンについて書いてあります。それを読みますと、select属性の式は、主にソース文書から処理の対象とするノードのリストを作るのに使われるのに対して、パターンはノードに適用するテンプレート規則を識別するのに使うという関係のようです。

パターンの構文は、式の構文のサブセットです。具体的には次のようになっています。

[1] Pattern ::= LocationPathPattern
| Pattern ‘|’ LocationPathPattern

パターンは一つのロケーションパスパターンまたは、それを’/’オペレータでつなげたものです。

[2] LocationPathPattern ::= ‘/’ RelativePathPattern?
| IdKeyPattern ((‘/’ | ‘//’) RelativePathPattern)?
| ‘//’? RelativePathPattern

[3] IdKeyPattern ::= ‘id’ ‘(‘ Literal ‘)’
| ‘key’ ‘(‘ Literal ‘,’ Literal ‘)’

IDkeyPatternは式では出てきませんでしたが、IDまたはkeyとなっています。あとは式としてのロケーションパスの生成規則で出てきたもの(第(3)回[5]を参照)と大よそ対応しているようです。

[4] RelativePathPattern ::= StepPattern
| RelativePathPattern ‘/’ StepPattern
| RelativePathPattern ‘//’ StepPattern
[5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate*
[6] ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier
| (‘child’ | ‘attribute’) ‘::’

ChildOrAttributeAxisSpecifierは、child軸とattribute軸のみになっています。

[1] XSLTを学ぶ (4) 式の構成部品としてのパスの使い方
[2] XML Path Language (XPath) Version 1.0
[3] XSL Transformations (XSLT) Version 1.0
[4] 『スタイルシート開発の基礎』
[5] XSLTを学ぶ (3) パスとは

【広告】★AH Formatter XML関連出版物の紹介

次回:
XSLTを学ぶ (6) ステップの文法を追求する

前回:
XSLTを学ぶ (4) 式の構成部品としてのパスの使い方

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ (4) 式の構成部品としてのパスの使い方

前回[1]はパス(ロケーションパス)の構成法を学びました。続いてパスの使い方を調べてみます。

スタイルシートで重要な役割を果たす要素の一つにxsl:apply-templatesがあります。XSLT[2]の5.4 Applying Template Rulesを見ますと、xsl:apply-templatesの定義は次のようになっています。

<xsl:apply-templates
 select = node-set-expression
 mode = qname>
 <!– Content: (xsl:sort | xsl:with-param)* –>
</xsl:apply-templates>

select属性を省略すると、xsl:apply-templatesはカレントノードのすべての子供を処理します。select属性の値に式を記述することで、処理対象とするノードの集合を限定できます。この式はどのように評価されるのでしょうか?

XSLTの5.1 Processing Modelを読むと、ノードにmatchするテンプレート規則の中から、あるテンプレート規則が選択されると、テンプレート規則はそのノードをカレントノードとして起動されるとあります。

本書[3]には次のような例(2.18の一部)が出ています。

<xsl:template match=”body”>
 <fo:page-sequence master-reference=”main”>
  <fo:flow flow-name=”xsl-region-body”>
   <xsl:apply-templates select=”p”/>
  </fo:flow>
 </fo:page-sequence>
</xsl:template>

<xsl:template match=”p”>
 <fo:block>
  <xsl:apply-templates/>
 </fo:block>
</xsl:template>

最初のブロックのテンプレート規則(xsl:template)は、(要素ノード)bodyにmatchしています。従って、最初のブロックではbodyがカレントノードです。

XPath[4]の式は文脈ノードで評価されます。XSLTの4 Expressionsを見ますと、最も外側の式(ある式の一部でない式)は文脈を次のように取得します。

a. 文脈ノードはカレントノードから
b. 文脈ノードの位置は、カレントノードリストにおけるカレントノードの位置から
c. 文脈ノードの大きさは、カレントノードリストの大きさから

こうして、最初のxsl:apply-templatesのselect属性の値である式p(child::pの省略記法)の文脈ノードはbodyになることが分かります。こうしてselect属性によりbodyの子であるpを選択したノード集合を作ることになります。(bodyの子のpではない要素ノードや、bodyの兄弟p要素ノードは対象になりません)。

[1] XSLTを学ぶ (3) パスとは
[2] XSL Transformations (XSLT) Version 1.0
[3] 『スタイルシート開発の基礎』
[4] XML Path Language (XPath) Version 1.0

【広告】★AH Formatter XML関連出版物の紹介

次回:
XSLTを学ぶ(5)パターンの記述のためのパス

前回:
XSLTを学ぶ (3) パスとは

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ (3) パスとは

現在、5月にPOD出版した『スタイルシート開発の基礎』[1]を使って、毎週、社内で勉強会をしています。先週は第2回目でしたが、3.4.1 パス(p.21)の箇所で人によっては結構ひっかかりました。

本書はXMLをXSL-FOで本にするということがテーマなので、XSLTの基本説明はさっと流しています。詳しいことはあとで、実際に使えれば良いという実践的な指導書ともいえます。でもわからないことは詳しく調べてみるのも面白いものです。ということで、このあたりを少し調べてみました。

まず、パスについて調べてみます。XPath仕様[2]を見ますと、パス(ロケーションパス)の生成規則では、次のように絶対パスと相対パスの2種類があります。

LocationPath ::= RelativeLocationPath | AbsoluteLocationPath

絶対パスは次のように相対パスの先頭が’/’(ルートノード)になっているものです。

AbsoluteLocationPath ::= ‘/’ RelativeLocationPath? | AbbreviatedAbsoluteLocationPath

相対パスは次のように単一のステップまたは複数のステップを’/’で結合して構築します。

RelativeLocationPath ::= Step | RelativeLocationPath ‘/’ Step | AbbreviatedRelativeLocationPath

‘/’の意味が場所によって違うことで混乱しがちですが、先頭に’/’があったら、それはルートノードを意味し、ステップの間の’/’は結合用オペレータです。

ステップの生成規則は次のようになっています。

Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep

つまり、ステップの記述方法には省略記法(AbbreviatedStep)と軸指定から始める書き方(AxisSpecifier NodeTest Predicate*で構成する)の二通りがあります。本書の3.4.1パスには省略記法、3.4.2軸には軸指定から始める記法の例が載っています。

前回([4])の図のp要素を含むパスは、省略記法では

絶対パス:/doc/body/p
相対パス:body/p

という二種類の書き方があります。これだけですと、WebのURLなどのパスの書き方と似ています。しかし、軸指定から始める書き方では、次のようになり違いが明確です。

絶対パス:/child::doc/child::body/child::p
相対パス:child::body/child::p

【注意】pを含む相対パスは、起点の取り方により、上記以外にもいろいろ書けます。

属性ノードも指定できます。軸から書くとき、例えば次のようになります。

絶対パス:/child::doc/child::body/child::p/attribute::s
相対パス:child::body/child::p/attribute::s

attribute:: は省略記法では@になります。

テキストノードは次のように指定できます。

絶対パス:/child::doc/child::body/child::p/child::text()
相対パス:child::body/child::p/text()

すべての子要素ノードを表すときは次のようにも書けます。

絶対パス:/child::doc/child::body/child::*
相対パス:child::body/child::*

ここで述べたロケーションパスは式の構成要素となります(本書3.4.4)。他にパタン(本書3.7.1)としてのパスもあります。本書ではあまり詳しく書いてありませんが[4]、Micheal Kayさんの本によれば、第一と第二ではパスの意味合いが違うようです。もう少し詳しく調べてみます。

[1] 『スタイルシート開発の基礎』
[2] XML Path Language (XPath) – W3C
[3] XSLTを学ぶ (1) XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う
[4] XSLTを学ぶ (2)ノードツリーとノードの親子、子孫関係
[5] なんども書きますが、本書はXSLTやXPathそのものを詳しく学ぶ本ではありません。

【ご注意】筆者はXSLTを勉強中です。ここに書いた内容は、資料を調べながら正確を期していますが、間違いを含んでいる可能性もありますので、ご注意ください。

次回:
XSLTを学ぶ(4)式の構成部品としてのパスの使い方

前回:
XSLTを学ぶ (2) ノードツリーとノードの親子、子孫関係

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ (2) ノードツリーとノードの親子、子孫関係

前回([1])はXPathでは7つのノードが定義されている、と説明しました。このうち重要なのは、ルートノード、要素ノード、属性ノード、テキストノードです。この4種類のノードについてもう少し詳しく見てみましょう。

例えば次のようなXML文書があったとします。このXMLの文書要素はdocです。

<!–?xml version=”1.0″?–>
 <doc>
  <body>
   <p s=”man1″>Hello! How are you?</p>
   <p s=”man2″>I am fine, thank you.</p>
  </body>
 </doc>

このXMLをXPathのノードツリーとして表しますと次のようになります。
XSLT

ノードには親子(parent, child)になるものがあります。ノードツリーで実線でしめした箇所が親子関係になります。子孫(descendant)ノードとはあるノードの子供と子供の子孫ノードです。

兄弟(sibling)ノードは同じ親の子供ノードです。

親になれるノードはルートノードと要素ノードのみです。子供になれるノードは要素ノードとテキストノードです。ルートノードは最上位ですので親をもちません。逆にテキストノードは最下位ですので子を持ちません。

やっかいなのは属性ノードです。要素には関連する属性があります。要素ノードはそれらの属性ノードの親です。しかし、属性ノードは要素の子ではないと規定されています。また属性ノードは子を持ちません。

属性ノードとして扱われるのは、要素に明示的に指定されているもの、または、DTDでデフォルト値が明示的に規定されているものです。DTDで値が#IMPLEDになっていて要素に指定されていない属性や、xml:lang、xml:spaceのようなある要素に指定されているとき、その子孫に継承することになっている属性は、その子孫では属性ノードとして扱われません。

テキストノードは、要素の内容の文字列をできるだけ長くなるように結合したものです。従って、テキストノードには、直前・直後の兄弟はありません。

要素ノードの文字列値とは、要素ノードの子孫であるテキストノードを、XML文書に現れる順に結合したものです。ルートノードの文字列置はXML文書のすべてのテキストです。

[1] XSLTを学ぶ (1) XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う
[2] XPath データモデル

★AH Formatter XML関連出版物の紹介

次回:
XSLTを学ぶ(3)パスとは

初回:
XSLTを学ぶ(1)XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う


XSLTを学ぶ (1) XMLのツリーモデルとXPath/XSLTのツリーモデルではルートの意味が違う

先月『スタイルシート開発の基礎』[1]という本を出版しました。この本は、副題に「XMLとFOで簡単な本を作ってみよう」とあるとおりXSLTの実践学習本です。現在、弊社の社内でも、初心者が集まって、この本を使ってXSLTの学習をはじめたところです[2]。私もメンバーの一人です。

『スタイルシート開発の基礎』のはじめにには「XSLT/XPathの知識はない」人が本書の対象とあります。私もXSLTを本格的に学ぶのは初めてですので、本書の想定読者にあてはまりそうです。

素直に読めば、この本だけで理解できるのかもしれませんが、折角ですので、他の参考資料や仕様書をにらみ合わせて楽しみながらお勉強。そこで、折角学んだことを整理して、紹介したいと思います。すでにご存知の方には、初歩的なお話と思いますが、『スタイルシート開発の基礎』の補足として役立てていただけるかもしれません。

資料としては次を見ています。

・『XSLTバイブル』(Michael Kay著、インプレス社、2002年1月発行)
・XSL Transformations (XSLT) Version 1.0(W3C Recommendation 16 November 1999)[3]
・XML Path Language (XPath) Version 1.0(W3C Recommendation 16 November 1999, revised 7 September 2015)[4]

さて、今回勉強し始めて知ったのですが、整形式XMLのツリーモデルとXSLT/XPathのツリーモデルはまったく違うんですね。

XML1.0では、整形式XML文書はルートが文書の実体ツリーの起点であり、XMLプロセサはルートから処理を始めます。さらに見ますと、ルートまたは文書要素と呼ばれる要素が唯一あるとされています。ルート要素は他の要素の内容になりません(つまり親を持ちません)が、他の要素は親を持ちます[5]。整形式XML文書はルート要素(文書要素)を起点とする要素のツリー構造になります。

しかし、XPathのデータモデルは、ノードという概念が中核です。ノードの種類として次の7つがあります。
・ルートノード(root nodes)
・要素ノード(element nodes)
・テキストノード(text nodes)
・属性ノード(attribute nodes)
・名前空間ノード(namespace nodes)
・処理命令ノード(processing instruction nodes)
・コメントノード(comment nodes)

原文でroot nodesと複数形になっているのが気になりますが、XPath仕様の5.1 ルートノード(Root Node)には、「ルートノードはツリーのルートであり」、「文書要素ノードはルートノードの子である」、「ルートノードの子供として、処理命令、処理命令のためのコメント、プロローグの中の文書要素の後のコメントノードがある。」とあります。

また、XSLT仕様の3 データモデル(Data Model)を見ますと、XSLTでは、ソース文書、スタイルシート、結果文書に同じデータモデルを使います。それらはXPathのデータモデルを基本として、少しだけ変更したものです。

・整形式のソースXML文書を読み込んでソースツリーを構築するときは、ルートノードの下にテキストノードはなく、唯一の要素ノードを子として持ちます。また、DOMなどの他の方法でソースツリーを作るときは、ソースツリーに対する制約は結果ツリー同様に緩められます。

・文書スタイルシートのツリーを構築するときは処理命令とコメントノードを無視します。

・結果ツリーでは、ルートノードへの制約が緩められており、子供として要素ノードを含む、任意のノードの系列をもつことができます。これにより、整形式XMLでない出力を作ることができます。

ですので、たぶん、XSLTでは整形式でないようなソースXMLでも処理できそうです[5]

[1] 『スタイルシート開発の基礎』
[2] アマゾンPODの便利な利用法
[3] XSL Transformations (XSLT) Version 1.0
[4] XML Path Language (XPath) Version 1.0
[5] Extensible Markup Language (XML) 1.0 (Fifth Edition) 2 Documents
[6] 余談です。『スタイルシート開発の基礎』の著者(神様)に、Michael Kayさんの本にそんなことが書いてある、と話しましたら、仕様書のどこに書いてあるかを示せ! と言われました。それは、3.1 Root Node Childrenの二つ目の段落の後半のセンテンスにあります。

次回:
XSLTを学ぶ(2)ノードツリーとノードの親子、子孫関係


Pages: Prev 1 2