<sect1 id="zend.dom.query">
    <title>Zend_Dom_Query</title>

    <para>
        <code>Zend_Dom_Query</code> предоставляет механизмы для запросов к
        документам XML и (X)HTML с использованием селекторов XPath и CSS.
        Он был разработан для того, чтобы помочь с функциональным тестированием
        приложений MVC, но может также использоваться для быстрой разработки
        кода, извлекающего нужные данные из выводимых данных приложения
        (например, XHTML-кода, возвращаемого сайтом).
    </para>

    <para>
        Нотация селекторов CSS предоставляется в качестве более простой и
        знакомой веб-разработчикам при произведении запросов к
        документам с XML-структурой.
        Эта нотация должна быть знакома всем, кто разрабатывает каскадные
        таблицы стилей или использует инструменты Javascript,
        имеющие функционал для получения узлов через селекторы CSS
        (именно функции <ulink url="http://prototypejs.org/api/utility/dollar-dollar">
            $$()</ulink> из Prototype и
        <ulink url="http://api.dojotoolkit.org/jsdoc/dojo/HEAD/dojo.query">
            dojo.query</ulink> из Dojo натолкнули автора на создание этой
        компоненты).
    </para>

    <sect2 id="zend.dom.query.operation">
        <title>Теория работы</title>

        <para>
            Для того, чтобы использовать <code>Zend_Dom_Query</code>,
            нужно инстанцировать объект <code>Zend_Dom_Query</code>,
            при этом можно передавать содержимое документа, к которому должны
            производиться запросы, в виде строки.
            Установив документ, вы можете использовать методы
            <code>query()</code> и <code>queryXpath()</code>. Эти методы будут
            возвращать объект <code>Zend_Dom_Query_Result</code>, который
            содержит в себе все найденные узлы.
        </para>

        <para>
            Основное отличие использования <code>Zend_Dom_Query</code> от
            применения связки DOMDocument + DOMXPath заключается в возможности
            извлечения через селекторы CSS. Вы можете использовать все
            перечисленное ниже, в любой комбинации:
        </para>

        <itemizedlist>
            <listitem><para>
                <emphasis>селекторы типа</emphasis>: основаны на типе
                элемента: 'div', 'a', 'span', 'h2' и т.д.
            </para></listitem>

            <listitem><para>
                <emphasis>селекторы класса</emphasis>: соответствуют атрибуту
                class элемента: '.error', 'div.error', 'label.required' и т.д.
                Если для элемента указано более одного класса, то этот элемент
                будет соотвествовать запросу, если указанный в запросе класс
                присутствует в его декларации.
            </para></listitem>

            <listitem><para>
                <emphasis>id-селекторы</emphasis>: соответствуют ID-атрибуту
                элемента: '#content', 'div#nav' и т.д.
            </para></listitem>

            <listitem>
                <para>
                    <emphasis>селекторы атрибута</emphasis>: соответствуют
                    атрибутам элемента. Используется три типа соответствия:
                </para>

                <itemizedlist>
                    <listitem><para>
                        <emphasis>точное соответствие</emphasis>: значение
                        атрибута в точности равно данной строке.
                        Запросу 'div[bar="baz"]' должен соответствовать элемент
                        div с атрибутом "bar", который имеет значение "baz".
                    </para></listitem>

                    <listitem><para>
                        <emphasis>соответствие слову</emphasis>: атрибут
                        содержит слово, которое в точности равно данной строке.
                        Запросу 'div[bar~="baz"]' должен соответствовать элемент
                        div с атрибутом "bar", который содержит слово "baz".
                        Элемент '&lt;div bar="foo baz"&gt;' будет
                        соответствовать этому запросу, но
                        '&lt;div bar="foo bazbat"&gt;' не будет.
                    </para></listitem>

                    <listitem><para>
                        <emphasis>соответствие подстроке</emphasis>:
                        атрибут содержит подстроку. Запросу 'div[bar*="baz"]'
                        должен соответствовать элемент div с атрибутом "bar",
                        который содержит внутри себя подстроку "baz".
                    </para></listitem>
                </itemizedlist>
            </listitem>

            <listitem><para>
                <emphasis>селекторы прямых потомков</emphasis>: используйте
                '&gt;' между селекторами для указания прямых потомков.
                'div > span' должен отбирать только те элементы 'span', которые
                являются прямыми потомками 'div'. Эти селекторы можно
                использовать с любыми селекторами, перечисленными выше.
            </para></listitem>

            <listitem>
                <para>
                    <emphasis>селекторы потомков</emphasis>: перечисляйте
                    селекторы через пробел для обозначения иерархии, вдоль
                    которой нужно производить поиск. 'div .foo span #one' должен
                    отбирать элемент с идентификатором 'one', который является
                    потомком любого уровня элемента 'span', который в свою
                    очередь является потомком любого уровня элемента класса
                    'foo', который является потомком любого уровня элемента
                    'div'. Например, такому запросу будет соответствовать
                    ссылка со словом 'One' в листинге ниже:
                </para>

                <programlisting language="html"><![CDATA[
<div>
<table>
    <tr>
        <td class="foo">
            <div>
                Lorem ipsum <span class="bar">
                    <a href="/foo/bar" id="one">One</a>
                    <a href="/foo/baz" id="two">Two</a>
                    <a href="/foo/bat" id="three">Three</a>
                    <a href="/foo/bla" id="four">Four</a>
                </span>
            </div>
        </td>
    </tr>
</table>
</div>
]]>
</programlisting>
            </listitem>
        </itemizedlist>

        <para>
            Выполнив запрос, вы можете работать с объектами результата для
            получения информации об узлах и извлечения самих узлов либо их
            содержимого для их исследования или манипуляций с ними.
            <code>Zend_Dom_Query_Result</code> реализует интерфейсы
            <code>Countable</code>, <code>Iterator</code>, и
            сохраняет результат как узлы DOMNode и элементы DOMElement.
            Для примера рассмотрим следующий вызов, который производит выборку
            из HTML-кода, приведенного выше:
        </para>

        <programlisting language="php"><![CDATA[
$dom = new Zend_Dom_Query($html);
$results = $dom->query('.foo .bar a');

$count = count($results); // получение числа соответствий: 4
foreach ($results as $result) {
    // переменная $result имеет тип DOMElement
}
]]>
        </programlisting>

        <para>
            <code>Zend_Dom_Query</code> также позволяет применять запросы
            XPath через метод <code>queryXpath()</code>. Вы можете передавать
            этому методу любые запросы XPath и в случае корректно составленного
            запроса он будет возвращать объект
            <code>Zend_Dom_Query_Result</code>.
        </para>
    </sect2>

    <sect2 id="zend.dom.query.methods">
        <title>Доступные методы</title>

        <para>
            Семейство классов <code>Zend_Dom_Query</code> имеет следующие
            доступные для использования методы.
        </para>

        <sect3 id="zend.dom.query.methods.zenddomquery">
            <title>Zend_Dom_Query</title>

            <para>
                В классе <code>Zend_Dom_Query</code> доступны следующие методы:
            </para>

            <itemizedlist>
                <listitem><para>
                    <code>setDocumentXml($document)</code>: принимает строку
                    с содержимым документа HTML, к которому должны производиться
                    запросы.
                </para></listitem>

                <listitem><para>
                    <code>setDocumentXhtml($document)</code>: принимает строку
                    с содержимым документа XHTML, к которому должны
                    производиться запросы.
                </para></listitem>

                <listitem><para>
                    <code>setDocumentHtml($document)</code>: принимает строку
                    с содержимым документа HTML, к которому должны производиться
                    запросы.
                </para></listitem>

                <listitem><para>
                    <code>setDocument($document)</code>: принимает строку без
                    указания типа документа. В этом случае
                    <code>Zend_Dom_Query</code> сам попытается определить тип
                    документа.
                </para></listitem>

                <listitem><para>
                    <code>getDocument()</code>: возвращает исходный документ,
                    переданный объекту.
                </para></listitem>

                <listitem><para>
                    <code>getDocumentType()</code>: возвращает тип документа,
                    переданного объекту. Это должна быть одна из
                    следующих констант класса Zend_Dom_Query:
                    <code>DOC_XML</code>, <code>DOC_XHTML</code> или
                    <code>DOC_HTML</code>.
                </para></listitem>

                <listitem><para>
                    <code>query($query)</code>: производит запрос к документу
                    с использованием нотации селекторов CSS.
                </para></listitem>

                <listitem><para>
                    <code>queryXpath($xPathQuery)</code>: производит запрос
                    к документу с использованием нотации XPath.
                </para></listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.dom.query.methods.zenddomqueryresult">
            <title>Zend_Dom_Query_Result</title>

            <para>
                Как было упомянуто ранее, <code>Zend_Dom_Query_Result</code>
                реализует интерфейсы <code>Iterator</code> и
                <code>Countable</code>, поэтому может использоваться в
                цикле <code>foreach</code> и с функцией <code>count()</code>.
                Кроме того, он предоставляет следующие методы:
            </para>

            <itemizedlist>
                <listitem><para>
                    <code>getCssQuery()</code>: возвращает запрос-селектор CSS,
                    который использовался для получения результата (если был).
                </para></listitem>

                <listitem><para>
                    <code>getXpathQuery()</code>: возвращает запрос XPath,
                    который использовался для получения результата.
                    <code>Zend_Dom_Query</code> неявным образом преобразует
                    запросы с селекторами CSS в запросы XPath, поэтому это
                    значение всегда будет заполняться.
                </para></listitem>

                <listitem><para>
                    <code>getDocument()</code>: возвращает объект DOMDocument,
                    к которому производился запрос.
                </para></listitem>
            </itemizedlist>
        </sect3>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
