TigerZF
🌐Español

30.2. Zend_Dom_Query

Zend_Dom_Query proporciona mecanismos para consultar documentos XML y (X)HTML utilizando XPath o selectores CSS. Se desarrolló para ayudar en las pruebas funcionales de aplicaciones MVC, pero también podría usarse para el desarrollo rápido de extractores de pantalla (screen scrapers).

La notación de selectores CSS se proporciona como una notación más simple y familiar para que los desarrolladores web la utilicen al consultar documentos con estructuras XML. La notación debería resultar familiar a cualquiera que haya desarrollado hojas de estilo en cascada o que utilice kits de herramientas de Javascript que proporcionen funcionalidad para seleccionar nodos utilizando selectores CSS ($$() de Prototype y dojo.query de Dojo fueron ambas inspiraciones para el componente).

30.2.1. Teoría de funcionamiento

Para usar Zend_Dom_Query, se instancia un objeto Zend_Dom_Query, pasando opcionalmente un documento a consultar (una cadena). Una vez que tiene un documento, puede usar los métodos query() o queryXpath(); cada método devolverá un objeto Zend_Dom_Query_Result con cualquier nodo coincidente.

La diferencia principal entre Zend_Dom_Query y usar DOMDocument + DOMXPath es la capacidad de seleccionar mediante selectores CSS. Puede utilizar cualquiera de los siguientes, en cualquier combinación:

  • tipos de elemento: proporcione un tipo de elemento a igualar: 'div', 'a', 'span', 'h2', etc.

  • atributos de estilo: atributos de estilo CSS a igualar: '.error', 'div.error', 'label.required', etc. Si un elemento define más de un estilo, esto coincidirá siempre que el estilo nombrado esté presente en cualquier parte de la declaración de estilo.

  • atributos id: atributos ID de elemento a igualar: '#content', 'div#nav', etc.

  • atributos arbitrarios: atributos de elemento arbitrarios a igualar. Se proporcionan tres tipos diferentes de coincidencia:

    • coincidencia exacta: el atributo coincide exactamente con la cadena: 'div[bar="baz"]' coincidiría con un elemento div con un atributo "bar" que coincide exactamente con el valor "baz".

    • coincidencia de palabra: el atributo contiene una palabra que coincide con la cadena: 'div[bar~="baz"]' coincidiría con un elemento div con un atributo "bar" que contiene la palabra "baz". '<div bar="foo baz">' coincidiría, pero '<div bar="foo bazbat">' no lo haría.

    • coincidencia de subcadena: el atributo contiene la cadena: 'div[bar*="baz"]' coincidiría con un elemento div con un atributo "bar" que contiene la cadena "baz" en cualquier parte.

  • descendientes directos: utilice '>' entre selectores para indicar descendientes directos. 'div > span' seleccionaría únicamente elementos 'span' que sean descendientes directos de un 'div'. También puede usarse con cualquiera de los selectores anteriores.

  • descendientes: encadene varios selectores para indicar una jerarquía a lo largo de la cual buscar. 'div .foo span #one' seleccionaría un elemento de id 'one' que es descendiente, a cualquier profundidad, de un elemento 'span', que a su vez es descendiente, a cualquier profundidad, de un elemento con clase 'foo', que es descendiente, a cualquier profundidad, de un elemento 'div'. Por ejemplo, coincidiría con el enlace de la palabra 'One' en el listado siguiente:

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

Una vez realizada su consulta, puede entonces trabajar con el objeto resultado para determinar información sobre los nodos, así como para extraerlos y/o su contenido directamente para su examen y manipulación. Zend_Dom_Query_Result implementa Countable e Iterator, y almacena los resultados internamente como DOMNodes y DOMElements. Como ejemplo, considere la siguiente llamada, que selecciona sobre el HTML anterior:

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

$count = count($results); // obtiene el número de coincidencias: 4
foreach ($results as $result) {
    // $result es un DOMElement
}

Zend_Dom_Query también permite consultas XPath directas utilizando el método queryXpath(); puede pasar cualquier consulta XPath válida a este método, y devolverá un objeto Zend_Dom_Query_Result.

30.2.2. Métodos disponibles

La familia de clases Zend_Dom_Query dispone de los siguientes métodos.

30.2.2.1. Zend_Dom_Query

Los siguientes métodos están disponibles para Zend_Dom_Query:

  • setDocumentXml($document): especifica una cadena XML para consultar.

  • setDocumentXhtml($document): especifica una cadena XHTML para consultar.

  • setDocumentHtml($document): especifica una cadena HTML para consultar.

  • setDocument($document): especifica una cadena para consultar; Zend_Dom_Query intentará entonces detectar automáticamente el tipo de documento.

  • getDocument(): recupera la cadena del documento original proporcionada al objeto.

  • getDocumentType(): recupera el tipo de documento del documento proporcionado al objeto; será una de las constantes de clase DOC_XML, DOC_XHTML, o DOC_HTML.

  • query($query): consulta el documento usando notación de selectores CSS.

  • queryXpath($xPathQuery): consulta el documento usando notación XPath.

30.2.2.2. Zend_Dom_Query_Result

Como se mencionó anteriormente, Zend_Dom_Query_Result implementa tanto Iterator como Countable, y como tal puede usarse en un bucle foreach(), así como con la función count(). Además, expone los siguientes métodos:

  • getCssQuery(): devuelve la consulta de selector CSS utilizada para producir el resultado (si la hay).

  • getXpathQuery(): devuelve la consulta XPath utilizada para producir el resultado. Internamente, Zend_Dom_Query convierte las consultas de selector CSS a XPath, por lo que este valor siempre estará poblado.

  • getDocument(): recupera el DOMDocument sobre el que se realizó la selección.