/lib/ZendFramework.old/library/Zend/Dom/Query.php

https://github.com/richjoslin/rivety · PHP · 223 lines · 101 code · 18 blank · 104 comment · 8 complexity · 4ab713a40b74288f6f04e32b07fac271 MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Dom
  17. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Query.php 20908 2010-02-04 19:00:54Z matthew $
  20. */
  21. /**
  22. * @see Zend_Dom_Query_Css2Xpath
  23. */
  24. require_once 'Zend/Dom/Query/Css2Xpath.php';
  25. /**
  26. * @see Zend_Dom_Query_Result
  27. */
  28. require_once 'Zend/Dom/Query/Result.php';
  29. /**
  30. * Query DOM structures based on CSS selectors and/or XPath
  31. *
  32. * @package Zend_Dom
  33. * @subpackage Query
  34. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  35. * @license http://framework.zend.com/license/new-bsd New BSD License
  36. */
  37. class Zend_Dom_Query
  38. {
  39. /**#@+
  40. * Document types
  41. */
  42. const DOC_XML = 'docXml';
  43. const DOC_HTML = 'docHtml';
  44. const DOC_XHTML = 'docXhtml';
  45. /**#@-*/
  46. /**
  47. * @var string
  48. */
  49. protected $_document;
  50. /**
  51. * Document type
  52. * @var string
  53. */
  54. protected $_docType;
  55. /**
  56. * Constructor
  57. *
  58. * @param null|string $document
  59. * @return void
  60. */
  61. public function __construct($document = null)
  62. {
  63. $this->setDocument($document);
  64. }
  65. /**
  66. * Set document to query
  67. *
  68. * @param string $document
  69. * @return Zend_Dom_Query
  70. */
  71. public function setDocument($document)
  72. {
  73. if (0 === strlen($document)) {
  74. return $this;
  75. }
  76. if ('<?xml' == substr(trim($document), 0, 5)) {
  77. return $this->setDocumentXml($document);
  78. }
  79. if (strstr($document, 'DTD XHTML')) {
  80. return $this->setDocumentXhtml($document);
  81. }
  82. return $this->setDocumentHtml($document);
  83. }
  84. /**
  85. * Register HTML document
  86. *
  87. * @param string $document
  88. * @return Zend_Dom_Query
  89. */
  90. public function setDocumentHtml($document)
  91. {
  92. $this->_document = (string) $document;
  93. $this->_docType = self::DOC_HTML;
  94. return $this;
  95. }
  96. /**
  97. * Register XHTML document
  98. *
  99. * @param string $document
  100. * @return Zend_Dom_Query
  101. */
  102. public function setDocumentXhtml($document)
  103. {
  104. $this->_document = (string) $document;
  105. $this->_docType = self::DOC_XHTML;
  106. return $this;
  107. }
  108. /**
  109. * Register XML document
  110. *
  111. * @param string $document
  112. * @return Zend_Dom_Query
  113. */
  114. public function setDocumentXml($document)
  115. {
  116. $this->_document = (string) $document;
  117. $this->_docType = self::DOC_XML;
  118. return $this;
  119. }
  120. /**
  121. * Retrieve current document
  122. *
  123. * @return string
  124. */
  125. public function getDocument()
  126. {
  127. return $this->_document;
  128. }
  129. /**
  130. * Get document type
  131. *
  132. * @return string
  133. */
  134. public function getDocumentType()
  135. {
  136. return $this->_docType;
  137. }
  138. /**
  139. * Perform a CSS selector query
  140. *
  141. * @param string $query
  142. * @return Zend_Dom_Query_Result
  143. */
  144. public function query($query)
  145. {
  146. $xpathQuery = Zend_Dom_Query_Css2Xpath::transform($query);
  147. return $this->queryXpath($xpathQuery, $query);
  148. }
  149. /**
  150. * Perform an XPath query
  151. *
  152. * @param string|array $xpathQuery
  153. * @param string $query CSS selector query
  154. * @return Zend_Dom_Query_Result
  155. */
  156. public function queryXpath($xpathQuery, $query = null)
  157. {
  158. if (null === ($document = $this->getDocument())) {
  159. require_once 'Zend/Dom/Exception.php';
  160. throw new Zend_Dom_Exception('Cannot query; no document registered');
  161. }
  162. $domDoc = new DOMDocument;
  163. $type = $this->getDocumentType();
  164. switch ($type) {
  165. case self::DOC_XML:
  166. $success = $domDoc->loadXML($document);
  167. break;
  168. case self::DOC_HTML:
  169. case self::DOC_XHTML:
  170. default:
  171. $success = $domDoc->loadHTML($document);
  172. break;
  173. }
  174. if (!$success) {
  175. require_once 'Zend/Dom/Exception.php';
  176. throw new Zend_Dom_Exception(sprintf('Error parsing document (type == %s)', $type));
  177. }
  178. $nodeList = $this->_getNodeList($domDoc, $xpathQuery);
  179. return new Zend_Dom_Query_Result($query, $xpathQuery, $domDoc, $nodeList);
  180. }
  181. /**
  182. * Prepare node list
  183. *
  184. * @param DOMDocument $document
  185. * @param string|array $xpathQuery
  186. * @return array
  187. */
  188. protected function _getNodeList($document, $xpathQuery)
  189. {
  190. $xpath = new DOMXPath($document);
  191. $xpathQuery = (string) $xpathQuery;
  192. if (preg_match_all('|\[contains\((@[a-z0-9_-]+),\s?\' |i', $xpathQuery, $matches)) {
  193. foreach ($matches[1] as $attribute) {
  194. $queryString = '//*[' . $attribute . ']';
  195. $attributeName = substr($attribute, 1);
  196. $nodes = $xpath->query($queryString);
  197. foreach ($nodes as $node) {
  198. $attr = $node->attributes->getNamedItem($attributeName);
  199. $attr->value = ' ' . $attr->value . ' ';
  200. }
  201. }
  202. }
  203. return $xpath->query($xpathQuery);
  204. }
  205. }