PageRenderTime 26ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Dom/Query.php

https://bitbucket.org/openfisma-ondemand/openfisma
PHP | 314 lines | 142 code | 25 blank | 147 comment | 14 complexity | c44cf0e753b36ec57884ed440c82b433 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, GPL-3.0, Apache-2.0, EPL-1.0
  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-2011 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  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-2011 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. * DOMDocument errors, if any
  52. * @var false|array
  53. */
  54. protected $_documentErrors = false;
  55. /**
  56. * Document type
  57. * @var string
  58. */
  59. protected $_docType;
  60. /**
  61. * Document encoding
  62. * @var null|string
  63. */
  64. protected $_encoding;
  65. /**
  66. * XPath namespaces
  67. * @var array
  68. */
  69. protected $_xpathNamespaces = array();
  70. /**
  71. * Constructor
  72. *
  73. * @param null|string $document
  74. * @return void
  75. */
  76. public function __construct($document = null, $encoding = null)
  77. {
  78. $this->setEncoding($encoding);
  79. $this->setDocument($document);
  80. }
  81. /**
  82. * Set document encoding
  83. *
  84. * @param string $encoding
  85. * @return Zend_Dom_Query
  86. */
  87. public function setEncoding($encoding)
  88. {
  89. $this->_encoding = (null === $encoding) ? null : (string) $encoding;
  90. return $this;
  91. }
  92. /**
  93. * Get document encoding
  94. *
  95. * @return null|string
  96. */
  97. public function getEncoding()
  98. {
  99. return $this->_encoding;
  100. }
  101. /**
  102. * Set document to query
  103. *
  104. * @param string $document
  105. * @param null|string $encoding Document encoding
  106. * @return Zend_Dom_Query
  107. */
  108. public function setDocument($document, $encoding = null)
  109. {
  110. if (0 === strlen($document)) {
  111. return $this;
  112. }
  113. // breaking XML declaration to make syntax highlighting work
  114. if ('<' . '?xml' == substr(trim($document), 0, 5)) {
  115. return $this->setDocumentXml($document, $encoding);
  116. }
  117. if (strstr($document, 'DTD XHTML')) {
  118. return $this->setDocumentXhtml($document, $encoding);
  119. }
  120. return $this->setDocumentHtml($document, $encoding);
  121. }
  122. /**
  123. * Register HTML document
  124. *
  125. * @param string $document
  126. * @param null|string $encoding Document encoding
  127. * @return Zend_Dom_Query
  128. */
  129. public function setDocumentHtml($document, $encoding = null)
  130. {
  131. $this->_document = (string) $document;
  132. $this->_docType = self::DOC_HTML;
  133. if (null !== $encoding) {
  134. $this->setEncoding($encoding);
  135. }
  136. return $this;
  137. }
  138. /**
  139. * Register XHTML document
  140. *
  141. * @param string $document
  142. * @param null|string $encoding Document encoding
  143. * @return Zend_Dom_Query
  144. */
  145. public function setDocumentXhtml($document, $encoding = null)
  146. {
  147. $this->_document = (string) $document;
  148. $this->_docType = self::DOC_XHTML;
  149. if (null !== $encoding) {
  150. $this->setEncoding($encoding);
  151. }
  152. return $this;
  153. }
  154. /**
  155. * Register XML document
  156. *
  157. * @param string $document
  158. * @param null|string $encoding Document encoding
  159. * @return Zend_Dom_Query
  160. */
  161. public function setDocumentXml($document, $encoding = null)
  162. {
  163. $this->_document = (string) $document;
  164. $this->_docType = self::DOC_XML;
  165. if (null !== $encoding) {
  166. $this->setEncoding($encoding);
  167. }
  168. return $this;
  169. }
  170. /**
  171. * Retrieve current document
  172. *
  173. * @return string
  174. */
  175. public function getDocument()
  176. {
  177. return $this->_document;
  178. }
  179. /**
  180. * Get document type
  181. *
  182. * @return string
  183. */
  184. public function getDocumentType()
  185. {
  186. return $this->_docType;
  187. }
  188. /**
  189. * Get any DOMDocument errors found
  190. *
  191. * @return false|array
  192. */
  193. public function getDocumentErrors()
  194. {
  195. return $this->_documentErrors;
  196. }
  197. /**
  198. * Perform a CSS selector query
  199. *
  200. * @param string $query
  201. * @return Zend_Dom_Query_Result
  202. */
  203. public function query($query)
  204. {
  205. $xpathQuery = Zend_Dom_Query_Css2Xpath::transform($query);
  206. return $this->queryXpath($xpathQuery, $query);
  207. }
  208. /**
  209. * Perform an XPath query
  210. *
  211. * @param string|array $xpathQuery
  212. * @param string $query CSS selector query
  213. * @return Zend_Dom_Query_Result
  214. */
  215. public function queryXpath($xpathQuery, $query = null)
  216. {
  217. if (null === ($document = $this->getDocument())) {
  218. // require_once 'Zend/Dom/Exception.php';
  219. throw new Zend_Dom_Exception('Cannot query; no document registered');
  220. }
  221. $encoding = $this->getEncoding();
  222. libxml_use_internal_errors(true);
  223. if (null === $encoding) {
  224. $domDoc = new DOMDocument('1.0');
  225. } else {
  226. $domDoc = new DOMDocument('1.0', $encoding);
  227. }
  228. $type = $this->getDocumentType();
  229. switch ($type) {
  230. case self::DOC_XML:
  231. $success = $domDoc->loadXML($document);
  232. break;
  233. case self::DOC_HTML:
  234. case self::DOC_XHTML:
  235. default:
  236. $success = $domDoc->loadHTML($document);
  237. break;
  238. }
  239. $errors = libxml_get_errors();
  240. if (!empty($errors)) {
  241. $this->_documentErrors = $errors;
  242. libxml_clear_errors();
  243. }
  244. libxml_use_internal_errors(false);
  245. if (!$success) {
  246. // require_once 'Zend/Dom/Exception.php';
  247. throw new Zend_Dom_Exception(sprintf('Error parsing document (type == %s)', $type));
  248. }
  249. $nodeList = $this->_getNodeList($domDoc, $xpathQuery);
  250. return new Zend_Dom_Query_Result($query, $xpathQuery, $domDoc, $nodeList);
  251. }
  252. /**
  253. * Register XPath namespaces
  254. *
  255. * @param array $xpathNamespaces
  256. * @return void
  257. */
  258. public function registerXpathNamespaces($xpathNamespaces)
  259. {
  260. $this->_xpathNamespaces = $xpathNamespaces;
  261. }
  262. /**
  263. * Prepare node list
  264. *
  265. * @param DOMDocument $document
  266. * @param string|array $xpathQuery
  267. * @return array
  268. */
  269. protected function _getNodeList($document, $xpathQuery)
  270. {
  271. $xpath = new DOMXPath($document);
  272. foreach ($this->_xpathNamespaces as $prefix => $namespaceUri) {
  273. $xpath->registerNamespace($prefix, $namespaceUri);
  274. }
  275. $xpathQuery = (string) $xpathQuery;
  276. if (preg_match_all('|\[contains\((@[a-z0-9_-]+),\s?\' |i', $xpathQuery, $matches)) {
  277. foreach ($matches[1] as $attribute) {
  278. $queryString = '//*[' . $attribute . ']';
  279. $attributeName = substr($attribute, 1);
  280. $nodes = $xpath->query($queryString);
  281. foreach ($nodes as $node) {
  282. $attr = $node->attributes->getNamedItem($attributeName);
  283. $attr->value = ' ' . $attr->value . ' ';
  284. }
  285. }
  286. }
  287. return $xpath->query($xpathQuery);
  288. }
  289. }