2012-06-23 2 views
1

Я хочу разобрать этот CSS Selector (и другие в подобной форме): div.class1#myid.class2[key=value]Regex для разбора CSS селектор

и он соответствует «.class1" и» .class2" , но я не могу понять то, что регулярное выражение для использования ..

пример: http://www.rubular.com/r/3dxpzyJLeK

в идеальном мире, я также хочу, чтобы извлечь:

  • типа (т.е. дел)
  • класс (т.е. список классов)
  • идентификатор (т.е. MyID)
  • ключ (т.е. ключ)
  • оператор (то есть =)
  • значение (т.е. значение)

, но я не могу получить основы идут!

Любая помощь будет массово оценили :)

Спасибо!

+3

Если вам нужна вся эта информация, вам лучше использовать что-то вроде [pyparsing] (http://pyparsing.wikispaces.com/). Также похоже, что уже есть несколько библиотек, которые уже делают это: http://cthedot.de/cssutils/ и http://code.google.com/p/css-py/ - хотя неясно, насколько они полны находятся. – BrenBarn

+0

Теоретически, может быть более одного '[key = value]', либо с использованием отдельных списков для ключа и значения, либо с использованием списка атрибутов, который содержит пары ключ-значение. И «тег» может быть более подходящим, чем «тип». –

+0

Плюс, существует больше вариантов атрибута с кавычками и без них для значений атрибутов: '[type]', '[type^= value]', '[type $ = value]' и т. Д., Если это имеет значение, так что может потребоваться также сохранить оператор атрибута. –

ответ

2

Спасибо всем большое за ваши предложения и помощь. Я связал все это в следующих двух REGEX Patterns:

Это один разбирает строку селектора CSS (например, DIV # myid.myclass [атр = 1, Фреда = 3]) http://www.rubular.com/r/2L0N5iWPEJ

cssSelector = re.compile(r'^(?P<type>[\*|\w|\-]+)?(?P<id>#[\w|\-]+)?(?P<classes>\.[\w|\-|\.]+)*(?P<data>\[.+\])*$') 

>>> cssSelector.match("table#john.test.test2[hello]").groups() 
('table', '#john', '.test.test2', '[hello]') 
>>> cssSelector.match("table").groups() 
('table', None, None, None) 
>>> cssSelector.match("table#john").groups() 
('table', '#john', None, None) 
>>> cssSelector.match("table.test.test2[hello]").groups() 
('table', None, '.test.test2', '[hello]') 
>>> cssSelector.match("table#john.test.test2").groups() 
('table', '#john', '.test.test2', None) 
>>> cssSelector.match("*#john.test.test2[hello]").groups() 
('*', '#john', '.test.test2', '[hello]') 
>>> cssSelector.match("*").groups() 
('*', None, None, None) 

И это один делает атрибуты (например, [ссылка, ключ ~ = значение]) http://www.rubular.com/r/2L0N5iWPEJ:

attribSelector = re.compile(r'(?P<word>\w+)\s*(?P<operator>[^\w\,]{0,2})\s*(?P<value>\w+)?\s*[\,|\]]') 

>>> a = attribSelector.findall("[link, ds9 != test, bsdfsdf]") 
>>> for x in a: print x 
('link', '', '') 
('ds9', '!=', 'test') 
('bsdfsdf', '', '') 

пару вещей отметить: 1) Это разбирает атрибуты с помощью запятой разграничении (так как я не использую строгой CSS). 2) Для этого требуются шаблоны в формате: тег, идентификатор, классы, атрибуты

Первое регулярное выражение делает маркеры, поэтому пробелы и «>» разделены части селекторной строки.Это потому, что я хотел использовать его для проверки на моем собственном объектном графике :)

Еще раз спасибо!

+0

Это действительно полезно, легко ли добавить часть psuedo? Как ': first-child'? Это действительно помогло бы мне. – Niels

1

Думаю, что вам что-то не так.

(?P<tag>[a-zA-Z]+)?(\.(?P<class>[a-zA-Z0-9_-]+)?)?(#(?P<id>[a-zA-Z0-9_-])?)?\W*\{((?P<name>[a-zA-Z0-9-_]+?)=(?P<value>[a-zA-Z0-9-_]+?))*\} 

К сожалению, если он не работает, я не проверял это

1

Определенно не пытайтесь сделать это с помощью одного регулярного выражения. Регулярные выражения, как известно, трудно читать и отлаживать, поэтому, когда вы заканчиваете работу с 80% этой задачи и возвращаетесь, чтобы исправить ошибку, код будет кошмаром.

Вместо этого попробуйте написать функции или даже класс, который позволит вам делать то, что вы хотите сделать. Затем вы можете использовать относительно простое регулярное выражение для каждой конкретной задачи и использовать гораздо более интуитивный синтаксис в своих реализациях.

class css_parser: 

    def __init__(self): 
    self.class_regexp = re.compile('\.[\w\-]*') # This is insufficient, but it's a start... 

    def get_class(self, str): 
    m = self.class_regexp.match(str) 
    return m.group(0) 

Вы хотите проконсультироваться The W3C CSS spec в частности раздел 4.