# Zend_Dom_Query

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

Нотация селекторов CSS предоставляется в качестве более простой и знакомой веб-разработчикам при произведении запросов к документам с XML-структурой. Эта нотация должна быть знакома всем, кто разрабатывает каскадные таблицы стилей или использует инструменты Javascript, имеющие функционал для получения узлов через селекторы CSS (именно функции $$() из Prototype и dojo.query из Dojo натолкнули автора на создание этой компоненты).

## Теория работы

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

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

- селекторы типа: основаны на типе элемента: 'div', 'a', 'span', 'h2' и т.д.

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

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

- селекторы атрибута: соответствуют атрибутам элемента. Используется три типа соответствия:

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

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

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

- селекторы прямых потомков: используйте '>' между селекторами для указания прямых потомков. 'div > span' должен отбирать только те элементы 'span', которые являются прямыми потомками 'div'. Эти селекторы можно использовать с любыми селекторами, перечисленными выше.

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

      <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>

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

    $dom = new Zend_Dom_Query($html);
    $results = $dom->query('.foo .bar a');

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

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

## Доступные методы

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

### Zend_Dom_Query

В классе `Zend_Dom_Query` доступны следующие методы:

- `setDocumentXml($document)`: принимает строку с содержимым документа HTML, к которому должны производиться запросы.

- `setDocumentXhtml($document)`: принимает строку с содержимым документа XHTML, к которому должны производиться запросы.

- `setDocumentHtml($document)`: принимает строку с содержимым документа HTML, к которому должны производиться запросы.

- `setDocument($document)`: принимает строку без указания типа документа. В этом случае `Zend_Dom_Query` сам попытается определить тип документа.

- `getDocument()`: возвращает исходный документ, переданный объекту.

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

- `query($query)`: производит запрос к документу с использованием нотации селекторов CSS.

- `queryXpath($xPathQuery)`: производит запрос к документу с использованием нотации XPath.

### Zend_Dom_Query_Result

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

- `getCssQuery()`: возвращает запрос-селектор CSS, который использовался для получения результата (если был).

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

- `getDocument()`: возвращает объект DOMDocument, к которому производился запрос.