【问题标题】:Regex to parse CSS selector正则表达式解析 CSS 选择器
【发布时间】:2012-06-25 17:17:48
【问题描述】:

我想解析这个 CSS 选择器(以及其他类似形式的选择器): div.class1#myid.class2[key=value]

让它匹配“.class1”和“.class2”,但我不知道要使用什么正则表达式..

示例:http://www.rubular.com/r/3dxpzyJLeK

在理想世界中,我还想提取:

  • 类型(即 div)
  • 类(即类列表)
  • id(即 myid)
  • 键(即键)
  • 运算符(即=)
  • 值(即值)

但我无法掌握基础知识!

任何帮助将不胜感激:)

谢谢!

【问题讨论】:

  • 如果您想要所有这些信息,最好使用pyparsing 之类的东西。看起来已经有几个库在这样做了——cthedot.de/cssutilscode.google.com/p/css-py——虽然还不清楚它们有多完整。
  • 理论上,[key=value] 可能不止一个,要么使用单独的键值列表,要么使用包含键值对的属性列表。而且“标签”可能比“类型”更合适。
  • 另外,属性有更多变体,属性值有无引号:[type][type^=value][type$=value] 等,如果这很重要,那么它可能是也需要存储属性运算符。
  • 学习语法:w3.org/TR/CSS21/grammar.html 并查看现有的 regex-for-CSS-selectors 问题:stackoverflow.com/questions/tagged/regex+css-selectors
  • 顺便说一句,“key”、“operator”和“value”不应单独解析 - 将它们一起解析为属性选择器,并可选地捕获 operator/value。

标签: python regex css-selectors


【解决方案1】:

非常感谢大家的建议和帮助。我将它们绑定到以下两个正则表达式模式中:

这个解析 CSS 选择器字符串(例如 div#myid.myclass[attr=1,fred=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)

而这个是属性(例如 [link,key~=value])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) 这要求模式采用以下格式:标签、ID、类、属性

第一个正则表达式执行标记,因此空格和“>”分隔选择器字符串的部分。这是因为我想用它来检查我自己的对象图:)

再次感谢!

【讨论】:

  • 这个真的很有帮助,添加伪部分容易吗?喜欢:first-child?这真的会帮助我。
  • @John 我想对 php 也一样。你能帮帮我吗
【解决方案2】:

绝对不要尝试使用单个正则表达式来执行此操作。正则表达式是出了名的难以阅读和调试,所以当你完成了这个任务的前 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 部分。

【讨论】:

    【解决方案3】:

    我认为你需要这样的东西。

    (?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-_]+?))*\}
    

    对不起,如果它不起作用,我没有测试它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-09
      • 2011-10-29
      • 1970-01-01
      • 2010-09-19
      • 2010-12-09
      • 2014-04-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多