オブジェクト索引
HTMLDocument オブジェクトは parseHtml() 関数の実行結果として得られる、テキスト表現の html 文書をパースした結果のオブジェクト(DOM)です。パースした html から CSS や jQuery のセレクタのような表記を使って、特定の要素を拾い出したり、また、html を加工して形を変えるなどの操作を行うことができます。
機能は限られていますが、ブラウザ上で JavaScript を使って DOM を操作するようなことが、テンプレートの展開やメソッド中で実行可能です。このオブジェクトは、主に、外部から直接取り込んだ html 文書を、テンプレート側で加工してコンテンツを生成する場合を想定して導入されました。下記のような局面で便利に使えるのではないでしょうか。
ページリソースの活用と、HTMLDocument を起点とする HTMLElement/HTMLElements/HTMLTextNode/HTMLComment などを使いこなすことで、外部からのコンテンツの取り込みを高度に実現できるようになるでしょう。
HTMLDocument オブジェクトの利用例を見てみましょう。
htmlText という複数行テキストの要素を持つテンプレートがあり、そのテンプレートで作成したページの、この要素の値に下記のような html が記述されている場合を考えます。ごく普通の小さな html 文書です。
なお、複数行テキストの要素の値が html 文書として扱われるためには、この要素の「HTMLで記述」属性が「可」に設定されており、かつ、ページ編集画面のこの要素の入力エリアの右にある「HTML」チェックボックスがチェックされている必要があります。
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<link rel="stylesheet" href="default.css" >
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="common/script.js"></script>
</head>
<body>
<h1>こんにちは</h1>
<ul>
<li>これは HTMLDocument オブジェクトの利用例です。</li>
<li>HTMLDocument を使うと HTMLをパースして加工してから利用することができます。</li>
</ul>
</body>
</html>
この html 文書を加工して、必要な部分を組み合わせて展開の中で使用する方法を少しずつ説明してゆきましょう。
<!DOCTYPE html>
<html>
<wr-variable name="document" value="parseHtml(htmlText)" />
<head>
</head>
<body>
</body>
</html>
まず、この htmlText から HTMLDocument オブジェクトを生成します。HTMLDocument オブジェクトを入手するためには parseHtml() 関数を使う必要があります。現在、それ以外の方法で HTMLDocument オブジェクトを入手することはできません。この展開例では wr-variable の変数 document に parseHtml() を実行した結果の HTMLDocument オブジェクトを取得しています。
次に head 節内に、htmlText から抽出した title を埋めこんでみましょう。
<!DOCTYPE html>
<html>
<wr-variable name="document" value="parseHtml(htmlText)" />
<head>
%document.head().select("title").first().outerHtml()%
</head>
<body>
</body>
</html>
document.head().select("title").first().outerHtml() という記述が加えられました。これにより、htmlText 中の title タグの部分が抽出され、その html 表現が outerHtml() メソッドにより head 節内に展開されます。各メソッドの詳細な説明は、それぞれのメソッド説明を参照してください。
title だけでなく、いろいろな要素を抽出してきて、展開することができます。style と link と script についても同じように展開してみましょう。
<!DOCTYPE html>
<html>
<wr-variable name="document" value="parseHtml(htmlText)" />
<head>
%document.head().select("title").first().outerHtml()%
%document.head().select("style").outerHtml()%
%document.head().select("link[rel=stylesheet]").outerHtml()%
%document.head().select("script").outerHtml()%
</head>
<body>
</body>
</html>
先の title では、複数書かれているかもしれない title タグの先頭だけを展開するために first() メソッドを使いましたが、style や link や script の場合には、複数記述されている場合にそれを全部取り込みたいので .first() で先頭のタグに限定することなくすべて展開しています。
なお、実際には、script や style などは何らかの特徴を使って展開するかどうかを決める必要があるかもしれません。select() メソッドは、CSS や jQuery のセレクタが書けるので、細かい抽出ができます。詳しくは select() メソッドの説明を参照してください。
link 要素については、rel=stylesheet の指定がある link 要素だけを抽出してきて head 節内に展開してみました。
さらに、body 内にも少し手を加え htmlText から抽出した要素を展開してみましょう。
<!DOCTYPE html>
<html>
<wr-variable name="document" value="parseHtml(htmlText)" />
<head>
%document.head().select("title").first().outerHtml()%
%document.head().select("style").outerHtml()%
%document.head().select("link[rel=stylesheet]").outerHtml()%
%document.head().select("script").outerHtml()%
</head>
<body>
<p>これは HTMLDocument オブジェクトの使い方サンプルです</p>
<div>
<p>以下の部分は htmlText から取り込んだコンテンツです</p>
%document.body().select("h1, ul").outerHtml()%
</div>
</body>
</html>
この展開を実行してみましょう。下記のような実行結果になるでしょう。htmlText から h1 要素と ul 要素が取り込まれているのが判ります。(尚 default.css などの url は、 preview 画面では preview 用の URL が使われるため、この結果とは少し違った結果になる場合があります)
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<link rel="stylesheet" href="default.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="common/script.js"></script>
</head>
<body>
<p>これは HTMLDocument オブジェクトの使い方サンプルです</p>
<div>
<p>以下の部分は htmlText から取り込んだコンテンツです</p>
<h1>こんにちは</h1>
<ul>
<li>これは HTMLDocument オブジェクトの利用例です。</li>
<li>HTMLDocument を使うと HTMLをパースして加工してから利用することができます。</li>
</ul>
</div>
</body>
</html>
メソッド名 | 説明 |
---|---|
body() | body タグの部分を切り出して HTMLElement オブジェクトとして返す |
getAllComments() | HTML文書中にあるすべてのコメントを返す |
head() | head タグの部分を切り出して HTMLElement オブジェクトとして返す |
html() | html 文書全体を文字列で返す |
nodeName() | 要素の型を文字列で返す |
select(selector) | 指定された CSS セレクタを満たす要素を選択して返す |
title() | title 要素の値を文字列で返す |
title(newTitle) | ドキュメントの title に newTitle で指定された文字列を設定する |
parseHtml() を使ってパースした html テキスト中の body タグの部分を切り出して HTMLElement オブジェクトとして返します。
下記のような html 文書を考えます。
<!DOCTYPE html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>This is test<h1>
<p>It's fine today.</p>
</body>
</html>
このような html テキストが入力されている htmlText という「複数行テキスト」の要素があるテンプレートを考えます。そのテンプレートの展開またはメソッドの中で、この html テキストをパースして HTMLDocument オブジェクトを入手します。
...
<wr-variable name="doc" value="parseHtml(htmlText)" />
...
このようなコードを実行することで doc という変数に HTMLDocument オブジェクトが得られます。
次に、この doc から body タグ部分を取り出します。
...
<wr-variable name="doc" value="parseHtml(htmlText)" />
<wr-variable name="body" value="doc.body()" />
...
このようなコードを実行することで body という変数に body タグの部分に対応する HTMLElement オブジェクトが得られます。
body 部分を展開またはメソッド結果として出力する場合には、outerHtml() メソッドを使います。
...
%body.outerHtml()%
...
実行結果は下記の用になるでしょう。
<body>
<h1>This is test<h1>
<p>It's fine today.</p>
</body>
body タグ自体は不要で、その内側だけ展開したい場合には outerHtml() の代わりに html() メソッドを使います。
...
%body.html()%
...
実行結果は下記の用になるでしょう。
<h1>This is test<h1>
<p>It's fine today.</p>
HTML文書中にあるすべてのコメントを返します。
HTMLComment オブジェクトの配列
htmlText という複数行テキストの要素を持つテンプレートがあり、そのテンプレートで作成したページの、この要素の値に下記のような html が記述されている場合を考えます。
<!DOCTYPE html>
<html>
<head>
<!-- コメント#0 -->
<title>Title</title>
</head>
<body>
<!-- コメント#1 -->
<p>
<!-- コメント#2 -->
今日は良い<em>天気<!-- コメント#3 --></em>です。
</p>
</body>
</html>
この html に対して文書内にあるすべてのコメントを抽出して展開に組込んでみましょう。
<!DOCTYPE html>
<html>
<head><title>Title</title></head>
<body>
<wr-for list="parseHtml(htmlText).getAllComments()" variable="comment">
%comment.outerHtml()%<br>
</wr-for>
</body>
</html>
parseHtml() 関数で htmlText をパースし、getAllComments() メソッドを呼び出してコメントのリストを取得します。
getAllComments() メソッドの戻り値は HTMLComment オブジェクトの配列です。そのまま wr-for の list= に指定することができます。
個々のコメントを outerHtml() メソッドで展開しています。
実行結果は下記のようになるでしょう。
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
</head>
<body>
<!-- コメント#0 -->
<br>
<!-- コメント#1 -->
<br>
<!-- コメント#2 -->
<br>
<!-- コメント#3 -->
<br>
</body>
</html>
HTMLElement オブジェクトにも同様のメソッドがあります。
head() メソッドは HTMLDocument から head 要素部分を取り出します。
head 要素部分に対応する HTMLElement オブジェクトを返します。
htmlText という複数行テキストの要素を持つテンプレートがあり、そのテンプレートで作成したページの、この要素の値に下記のような html が記述されている場合を考えます。
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<meta charset="UTF-8">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="/default.css" type="text/css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
この html の head 節内のコードを展開に組み込んでみましょう。
<!DOCTYPE html>
<html>
<head>
%parseHtml(htmlText).head().html()%
</head>
<body>
ここには、このページのコンテンツを展開します。
</body>
</html>
parseHtml(htmlText) で htmlText をパースして HTMLDocument オブジェクトを取得します。その後、head() メソッドで head 要素を取り出してから html() メソッドで head 要素内のコードを展開に組込んでいます。
この展開の実行結果は下記のようになるでしょう。
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<meta charset="UTF-8">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="/default.css" type="text/css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
ここには、このページのコンテンツを展開します。
</body>
</html>
このような記述をすれば htmlText 中の head の部分を切り出してコンテンツに組込むことができます。この例では、head の中をすべて切り出して組込みましたが、select() メソッドを使えば、選択的に切り取ってコンテンツに組込むことが可能です。
この要素の内側の各子要素の html を生成して返します。
この HTMLDocument の html 表現が文字列で返されます。
htmlText という複数行テキストの要素を持つテンプレートがあり、そのテンプレートで作成したページの、この要素の値に下記のような html が記述されている場合を考えます。
<!DOCTYPE html>
<html>
<head><title>Title</title></head>
<body>
<p>
こんにちは!
<img src="a.png">
</p>
<img src="b.gif">
</body>
</html>
この htmlText の中の img 要素だけを削除した html を生成して展開結果としてみましょう。
<wr-variable name="doc" value="parseHtml(htmlText)" />
%doc.select("img").remove()%
%doc.html()%
最初に parseHtml() 関数を使って htmlText をパースし HTMLDocument オブジェクトを生成します。生成した HTMLDocument オブジェクトは doc という変数に保持しておきます。 doc の中にある img 要素を select("img") で抽出し、remove() を実行してすべて削除します。 最後に doc.html() メソッドで、img 要素が削除された後の html を生成して展開結果としています。 この展開例の実行結果は下記のようになるでしょう。
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
</head>
<body>
<p> こんにちは! </p>
</body>
</html>
html() メソッドで要素の html 表現を生成すると、エスケープが必要な文字、例えば & や < > などは、状況に応じて適切にエスケープされた状態で返されます。メソッド名が表しているとおり、返される文字列は、妥当性のある html テキストです。さらなるエスケープ処理は必要ありません。このあたりの動作は html() メソッドと text() メソッドとで異なる点に注意してください。
要素の型を返します。childNodes() メソッドなどを呼び出すと、型の判らない子要素の配列が得られますが、各子要素の型を調べる時に nodeName() メソッドが役立ちます。
要素の型の名前を文字列で返します。HTMLDocument オブジェクトに対してこのメソッドを呼び出すと "HTMLDocument" が返されます。
select() は HTMLDocument 全体から指定された CSS セレクタを満たす要素を選択して返します。
選択条件を指定する CSS セレクタを与えます。空文字列は与えられません。
条件を満たす HTMLElement オブジェクトを含んだ HTMLElements オブジェクトが返されます。
HTMLDocument オブジェクトの select() メソッドの動作は、その抽出対象が文書全体の HTMLDocument であることを除いて HTMLElement の select() メソッドと同じです。
使用方法や selector に指定可能な表現については HTMLElement の select() メソッドを参照してください。
この HTMLDocument の head 節内にある title 要素の値を返します。
title 要素の値を文字列で返します。
htmlText という複数行テキストの要素を持つテンプレートがあり、そのテンプレートで作成したページの、この要素の値に下記のような html が記述されている場合を考えます。
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
この htmlText に記述されている title 要素の値を取り出すコードは下記のようになります。
parseHtml() 関数で htmlText をパースしてから title() メソッドを呼び出すことで htmlText 中の title 要素の値(内容)を取り出すことができます。
....
%parseHtml(htmlText).title()%
....
このドキュメントのタイトルに newTitle で指定された文字列を設定します。
設定するタイトルを文字列で指定してください。
null が返されます。
htmlText という複数行テキストの要素を持つテンプレートがあり、そのテンプレートで作成したページの、この要素の値に下記のような html が記述されている場合を考えます。
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<meta charset="UTF-8">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="/default.css" type="text/css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
この htmlText を、基本的にそのまま展開結果として使用するのですが、タイトルだけは、ページのタイトルに書き換えて展開を生成してみます。
<wr-variable name="html" value="parseHtml(htmlText)" />
%html.title(pageTitle())%
%html.html()%
parseHtml() 関数を使って htmlText をパースし HTMLDocument オブジェクトを入手して変数 html に保持しておきます。
入手した HTMLDocument オブジェクトに title(pageTitle()) メソッドを実行し、ページに付けられているタイトル(pageTitle() 関数で取得します)をパースした html のタイトルに設定します。
最後に html.html() で、タイトルを書き換えた htmlText 全体を展開結果に使用しています。
ページのタイトルに「ページのタイトル」が指定されている場合の実行結果は下記の通りになるでしょう。
<!DOCTYPE html>
<html>
<head>
<title>ページのタイトル</title>
<meta charset="UTF-8">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="/default.css" type="text/css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<p>Hello World!</p>
</body>
</html>