1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 21585 -->
4 <sect1 id="zend.dom.query">
5 <title>Zend_Dom_Query</title>
8 <classname>Zend_Dom_Query</classname> を使用すると、<acronym>XML</acronym> や (X)<acronym>HTML</acronym> ドキュメントに対して
9 XPath あるいは <acronym>CSS</acronym> セレクタを用いた問い合わせができるようになります。
10 <acronym>MVC</acronym> アプリケーションの機能テストを支援するために作られたものですが、
11 スクリーンスクレイパーを手早く作成するためにも使うことができます。
15 <acronym>CSS</acronym> セレクタ記法は、ウェブ開発者にとってはシンプルでなじみのある記法です。
16 <acronym>XML</acronym> 構造のドキュメントに対する問い合わせに使用できます。
17 この記法は、スタイルシートを扱ったことのある人ならきっとおなじみでしょうし、
18 Javascript のツールキットの中にも
19 <acronym>CSS</acronym> セレクタを使用してノードを選択できる機能を持つものがあります
20 (<ulink url="http://prototypejs.org/api/utility/dollar-dollar">Prototype の
22 <ulink url="http://api.dojotoolkit.org/jsdoc/dojo/HEAD/dojo.query">Dojo の
23 dojo.query</ulink> をヒントにしてこのコンポーネントを作成しました)。
26 <sect2 id="zend.dom.query.operation">
30 <classname>Zend_Dom_Query</classname> を使用するには、
31 <classname>Zend_Dom_Query</classname> オブジェクトのインスタンスを作成します。
32 その際に、問い合わせたいドキュメント (文字列)
35 <methodname>query()</methodname> メソッドあるいは <methodname>queryXpath()</methodname>
36 メソッドを使用できます。どちらのメソッドも、
37 マッチしたノードを含む <classname>Zend_Dom_Query_Result</classname>
42 <classname>Zend_Dom_Query</classname> を使うことと
43 DOMDocument + DOMXPath を使うことの最大の違いは、
44 <acronym>CSS</acronym> セレクタによる選択が可能かどうかということです。
45 以下の内容を、任意の組み合わせで使用できます。
50 <emphasis>要素型</emphasis>: マッチさせたい要素の型を指定します。
51 'div', 'a', 'span', 'h2' などです。
55 <emphasis>style 属性</emphasis>: マッチさせたい <acronym>CSS</acronym> style
56 属性を指定します。'<command>.error</command>', '<command>div.error</command>', '<command>label.required</command>'
57 などです。ひとつの要素に複数のスタイルが定義されている場合は
58 指定したスタイルがスタイル宣言のどこかに存在すればマッチします。
62 <emphasis>id 属性</emphasis>: マッチさせたい要素 ID 属性を指定します。
63 '#content', 'div#nav' などです。
68 <emphasis>任意の属性</emphasis>:
70 以下の 3 種類のマッチ形式を用意しています。
75 <emphasis>完全マッチ</emphasis>: その文字列に完全にマッチする属性。
76 'div[bar="baz"]' は、"bar" 属性の値が正確に "baz"
81 <emphasis>単語マッチ</emphasis>:
83 'div[bar~="baz"]' は、"bar" 属性の値に単語 "baz"
85 '<div bar="foo baz">' はマッチしますが、 '<div
86 bar="foo bazbat">' はマッチしません。
90 <emphasis>部分文字列マッチ</emphasis>:
91 その文字列を含む属性。'div[bar*="baz"]' は、
92 "bar" 属性の値のどこかに文字列 "baz"
99 <emphasis>直接の子孫</emphasis>:
100 セレクタの間で '>' を使用すると、
101 直接の子要素であることを表します。'div > span'
102 は、'span' 要素のうち 'div' の直接の子であるものだけを選択します。
108 <emphasis>子孫</emphasis>:
109 複数のセレクタをひとつの文字列にまとめると、
111 '<command>div .foo span #one</command>' が探すのは id が 'one'
113 要素の子孫 (その間の階層の数は問わない) であり、
114 さらにその 'span' 要素はクラス 'foo' の要素の子孫
116 同様に、そのクラス 'foo' の要素は 'div' 要素の子孫
117 (その間の階層の数は問わない) となります。
118 これは、たとえば以下のリストにおける単語 'One'
122 <programlisting language="html"><![CDATA[
128 Lorem ipsum <span class="bar">
129 <a href="/foo/bar" id="one">One</a>
130 <a href="/foo/baz" id="two">Two</a>
131 <a href="/foo/bat" id="three">Three</a>
132 <a href="/foo/bla" id="four">Four</a>
144 問い合わせを実行したら、その結果のオブジェクトを用いてノードの情報を取得したり、
145 そのノード (あるいはノードの内容) を取り出して操作したりできます。
146 <classname>Zend_Dom_Query_Result</classname> は <classname>Countable</classname>
147 と <classname>Iterator</classname> を実装しており、内部では結果を
148 DOMNodes および DOMElements で保持しています。
149 たとえば、次のようなコードを上の <acronym>HTML</acronym> に対して実行することを考えてみましょう。
152 <programlisting language="php"><![CDATA[
153 $dom = new Zend_Dom_Query($html);
154 $results = $dom->query('.foo .bar a');
156 $count = count($results); // マッチした数: 4
157 foreach ($results as $result) {
158 // $result は DOMElement です
163 <classname>Zend_Dom_Query</classname> では、
164 <methodname>queryXpath()</methodname> メソッドで
165 XPath クエリを直接使用することもできます。
166 XPath クエリとして正しいものならなんでもこのメソッドに渡すことができ、
167 結果は <classname>Zend_Dom_Query_Result</classname> オブジェクトで返されます。
171 <sect2 id="zend.dom.query.methods">
172 <title>使用可能なメソッド</title>
175 <classname>Zend_Dom_Query</classname> 系のクラスでは、次のメソッドが使用できます。
178 <sect3 id="zend.dom.query.methods.zenddomquery">
179 <title>Zend_Dom_Query</title>
183 <classname>Zend_Dom_Query</classname> で使用できます。
188 <methodname>setDocumentXml($document)</methodname>:
189 対象となる <acronym>XML</acronym> 文字列を指定します。
193 <methodname>setDocumentXhtml($document)</methodname>:
194 対象となる <acronym>XHTML</acronym> 文字列を指定します。
198 <methodname>setDocumentHtml($document)</methodname>:
199 対象となる <acronym>HTML</acronym> 文字列を指定します。
203 <methodname>setDocument($document)</methodname>:
204 対象となる文字列を指定します。<classname>Zend_Dom_Query</classname>
209 <methodname>getDocument()</methodname>:
210 オブジェクトに渡した元の文字列を取得します。
214 <methodname>getDocumentType()</methodname>:
215 オブジェクトに渡したドキュメントの形式を取得します。
216 クラス定数 <constant>DOC_XML</constant>、<constant>DOC_XHTML</constant>
217 あるいは <constant>DOC_HTML</constant> のいずれかとなります。
221 <methodname>query($query)</methodname>:
222 <acronym>CSS</acronym> セレクタ記法でドキュメントへの問い合わせを行います。
226 <methodname>queryXpath($xPathQuery)</methodname>:
227 XPath 記法でドキュメントへの問い合わせを行います。
232 <sect3 id="zend.dom.query.methods.zenddomqueryresult">
233 <title>Zend_Dom_Query_Result</title>
236 先ほど説明したように、<classname>Zend_Dom_Query_Result</classname>
237 は <classname>Iterator</classname> と
238 <classname>Countable</classname> を実装しており、
239 <classname>foreach</classname> ループで使用したり
240 <methodname>count()</methodname> 関数を利用したりできます。
246 <methodname>getCssQuery()</methodname>:
247 その結果を得る元となった <acronym>CSS</acronym> セレクタクエリを
252 <methodname>getXpathQuery()</methodname>:
253 その結果を得る元となった XPath クエリを返します。
254 内部的には、<classname>Zend_Dom_Query</classname> は
255 <acronym>CSS</acronym> セレクタクエリを XPath に変換しています。
256 そのため、このメソッドは常に結果を返します。
260 <methodname>getDocument()</methodname>:
261 問い合わせ対象となった DOMDocument を取得します。