1# PhpCss - PHP CSS Parser Library
2
3[![Build Status](https://travis-ci.org/ThomasWeinert/PhpCss.svg?branch=master)](https://travis-ci.org/ThomasWeinert/PhpCss)
4[![License](https://poser.pugx.org/carica/phpcss/license.svg)](https://packagist.org/packages/carica/phpcss)
5[![Total Downloads](https://poser.pugx.org/carica/phpcss/downloads.svg)](https://packagist.org/packages/carica/phpcss)
6[![Latest Stable Version](https://poser.pugx.org/carica/phpcss/v/stable.svg)](https://packagist.org/packages/carica/phpcss)
7[![Latest Unstable Version](https://poser.pugx.org/carica/phpcss/v/unstable.svg)](https://packagist.org/packages/carica/phpcss)
8
9* License: The MIT License
10* Copyright: 2010-2018 PhpCss Team
11* Author: [Thomas Weinert](http://thomas.weinert.info) <thomas@weinert.info>
12
13Thanks to Benjamin Eberlei, Bastian Feder and Jakob Westhoff for ideas and concepts.
14
15PhpCSS is a parser for CSS 3 selectors. It parses them into an AST and allows them to compile the AST to CSS selectors or Xpath expressions.
16
17The main target of this project is the possibilty to convert CSS selectors into Xpath expressions.
18
19## Demo
20
21A small demo application can be found at: http://xpath.thomas.weinert.info/
22
23## Installation
24
25PhpCss is available on Packagist: [Carica/PhpCss](https://packagist.org/packages/carica/phpcss).
26Add it to you composer.json and update.
27
28## Basic Usage
29
30Get CSS selector as Xpath expression
31
32    $expression = PhpCss::toXpath($selector);
33
34Reformat/Validate CSS Selector
35
36    $selector = PhpCss::reformat($selector);
37
38Get the AST
39
40    $ast = PhpCss::getAst($selector);
41
42
43## FluentDOM
44
45[FluentDOM 5](https://github.com/FluentDOM/FluentDOM) allows to inject a callback to convert selectors. If you have FluentDOM and PhpCss installed in your project, you can use CSS selectors in FluentDOM:
46
47    $fd = FluentDOM::QueryCss($xml);
48    $fd
49      ->find('td:nth-of-type(even)')
50      ->addClass('even');
51
52## Supported
53
54<table width="100%">
55  <thead>
56    <tr>
57      <th>Selector</th><th>to CSS</th><th>to Xpath</th>
58    </tr>
59  </thead>
60  <tbody>
61    <tr>
62      <td>*</td><td>✓</td><td>✓</td>
63    </tr>
64    <tr>
65      <td>E</td><td>✓</td><td>✓</td>
66    </tr>
67    <tr>
68      <td>ns|*</td><td>✓</td><td>✓</td>
69    </tr>
70    <tr>
71      <td>ns|E</td><td>✓</td><td>✓</td>
72    </tr>
73    <tr>
74      <th colspan="3">Attributes</th>
75    </tr>
76    <tr>
77      <td>E[foo]</td><td>✓</td><td>✓</td>
78    </tr>
79    <tr>
80      <td>E[foo="bar"]</td><td>✓</td><td>✓</td>
81    </tr>
82    <tr>
83      <td>E[foo~="bar"]</td><td>✓</td><td>✓</td>
84    </tr>
85    <tr>
86      <td>E[foo^="bar"]</td><td>✓</td><td>✓</td>
87    </tr>
88    <tr>
89      <td>E[foo$="bar"]</td><td>✓</td><td>✓</td>
90    </tr>
91    <tr>
92      <td>E[foo*="bar"]</td><td>✓</td><td>✓</td>
93    </tr>
94    <tr>
95      <td>E[foo|="bar"]</td><td>✓</td><td>✓</td>
96    </tr>
97    <tr>
98      <th colspan="3">Structural Pseudo Classes</th>
99    </tr>
100    <tr>
101      <td>E:root</td><td>✓</td><td>✓</td>
102    </tr>
103    <tr>
104      <td>E:nth-child(42)</td><td>✓</td><td>✓</td>
105    </tr>
106    <tr>
107      <td>E:nth-last-child(42)</td><td>✓</td><td>✓</td>
108    </tr>
109    <tr>
110      <td>E:nth-of-type(42)</td><td>✓</td><td>✓</td>
111    </tr>
112    <tr>
113      <td>E:nth-last-of-type(42)</td><td>✓</td><td>✓</td>
114    </tr>
115    <tr>
116      <td>E:first-child</td><td>✓</td><td>✓</td>
117    </tr>
118    <tr>
119      <td>E:last-child</td><td>✓</td><td>✓</td>
120    </tr>
121    <tr>
122      <td>E:first-of-type</td><td>✓</td><td>✓</td>
123    </tr>
124    <tr>
125      <td>E:last-of-type</td><td>✓</td><td>✓</td>
126    </tr>
127    <tr>
128      <td>E:only-child</td><td>✓</td><td>✓</td>
129    </tr>
130    <tr>
131      <td>E:only-of-type</td><td>✓</td><td>✓</td>
132    </tr>
133    <tr>
134      <td>E:empty</td><td>✓</td><td>✓</td>
135    </tr>
136    <tr>
137      <th colspan="3">Link Pseudo Classes</th>
138    </tr>
139    <tr>
140      <td>E:link</td><td>✓</td><td>✗</td>
141    </tr>
142    <tr>
143      <td>E:visited</td><td>✓</td><td>✗</td>
144    </tr>
145    <tr>
146      <th colspan="3">User Action Pseudo Classes</th>
147    </tr>
148    <tr>
149      <td>E:active</td><td>✓</td><td>✗</td>
150    </tr>
151    <tr>
152      <td>E:hover</td><td>✓</td><td>✗</td>
153    </tr>
154    <tr>
155      <td>E:focus</td><td>✓</td><td>✗</td>
156    </tr>
157    <tr>
158      <th colspan="3">Target Pseudo Class</th>
159    </tr>
160    <tr>
161      <td>E:target</td><td>✓</td><td>✗</td>
162    </tr>
163    <tr>
164      <th colspan="3">Language Pseudo Class</th>
165    </tr>
166    <tr>
167      <td>E:lang(fr)</td><td>✓</td><td>✓</td>
168    </tr>
169    <tr>
170      <th colspan="3">UI Element states Pseudo Class</th>
171    </tr>
172    <tr>
173      <td>E:enabled</td><td>✓</td><td>✓ (not disabled)</td>
174    </tr>
175    <tr>
176      <td>E:disabled</td><td>✓</td><td>✓ (attribute)</td>
177    </tr>
178    <tr>
179      <td>E:checked</td><td>✓</td><td>✓ (attribute)</td>
180    </tr>
181    <tr>
182      <th colspan="3">Pseudo Elements</th>
183    </tr>
184    <tr>
185      <td>E:first-line</td><td>✓</td><td>✗</td>
186    </tr>
187    <tr>
188      <td>E:first-letter</td><td>✓</td><td>✗</td>
189    </tr>
190    <tr>
191      <td>E:before</td><td>✓</td><td>✗</td>
192    </tr>
193    <tr>
194      <td>E:after</td><td>✓</td><td>✗</td>
195    </tr>
196    <tr>
197      <th colspan="3">Class Selector</th>
198    </tr>
199    <tr>
200      <td>E.warning</td><td>✓</td><td>✓</td>
201    </tr>
202    <tr>
203      <th colspan="3">Id Selector</th>
204    </tr>
205    <tr>
206      <td>E#myid</td><td>✓</td><td>✓</td>
207    </tr>
208    <tr>
209      <th colspan="3">Negation Pseudo Class</th>
210    </tr>
211    <tr>
212      <td>E:not(s)</td><td>✓</td><td>✓</td>
213    </tr>
214    <tr>
215      <th colspan="3">Combinators</th>
216    </tr>
217    <tr>
218      <td>E F</td><td>✓</td><td>✓</td>
219    </tr>
220    <tr>
221      <td>E > F</td><td>✓</td><td>✓</td>
222    </tr>
223    <tr>
224      <td>E + F</td><td>✓</td><td>✓</td>
225    </tr>
226    <tr>
227      <td>E ~ F</td><td>✓</td><td>✓</td>
228    </tr>
229    <tr>
230      <th colspan="3">jQuery</th>
231    </tr>
232    <tr>
233      <td>:contains("text")</td><td>✓</td><td>✓</td>
234    </tr>
235    <tr>
236      <td>:has(s)</td><td>✓</td><td>✓</td>
237    </tr>
238    <tr>
239      <td>:gt(42)</td><td>✓</td><td>✓</td>
240    </tr>
241    <tr>
242      <td>:lt(42)</td><td>✓</td><td>✓</td>
243    </tr>
244    <tr>
245      <td>:odd</td><td>✓</td><td>✓</td>
246    </tr>
247    <tr>
248      <td>:even</td><td>✓</td><td>✓</td>
249    </tr>
250  </tbody>
251</table>
252