PyParsing - nestedExpr和匹配标记

时间:2013-01-09 12:43:51

标签: python xml-parsing pyparsing

我在今天早些时候提出了一个关于同一问题的问题,但由于解决方案是切换库,我现在对其他库有问题,因为我打开另一个问题...希望'很好。

所以我不想匹配以下标记:

<text link="no">
    ...
</text>

我不在乎文本中的内容是什么,文本具有该链接属性。

我现在使用pyparsing如下:

def content_must_not_be_empty_string(tokens):
    if tokens[0]=="":
        raise ParseException("content cannot be empty")

text_start = Regex('<text[^<]*>')
text_no_start = Regex('<text[^<]*link="no"[^<]*>')
text_no_end = Regex('</text>[ \t\n\r\xa0]*')
text_no_content = SkipTo(text_no_start | text_no_end | text_start)
text_no_content.setParseAction(content_must_not_be_empty_string)
text_no = nestedExpr(text_no_start,text_no_end,text_no_content)
text_no.setParseAction(somemethod)

起初整个事情由于空标记而循环,这就是我添加content_must_not_be_empty的原因。

现在它不再循环,但某些方法也没有执行。

非常感谢帮助。

2 个答案:

答案 0 :(得分:2)

严格来说,pyparsing不是XML解析库,但它确实包含一些内置支持,用于从XML和HTML中提取数据,而不是解析整个文档。我并不是说你可以在Regex元素中嵌入正则表达式。相反,请查看使用makeXMLTags或makeHTMLTags:

>>> sample = """<text link="no"> lskdjflskdjf </text>"""
>>> text_start,text_end = makeXMLTags("text")
>>> text_start_no = text_start.copy().setParseAction(withAttribute(link="no"))
>>> expr1 = text_start_no + SkipTo(text_end)('body') + text_end
>>> print expr1.parseString(sample)
['text', ['link', 'no'], False, 'lskdjflskdjf ', '</text>']
>>> print expr1.parseString(sample).dump()
['text', ['link', 'no'], False, 'lskdjflskdjf ', '</text>']
- body: lskdjflskdjf 
- empty: False
- endText: </text>
- link: no
- startText: ['text', ['link', 'no'], False]
  - empty: False
  - link: no

从XML或HTML中提取数据时,这将解决各种意外情况。

现在,如果你实际上有嵌套标签,那么你需要开始钻研到nestedExpr区域。

>>> sample2 = """<text link="no"> lskdjflskdjf<text>more</text> </text>"""

但我仍然鼓励您使用makeXMLTags或makeHTMLTags构建标记结构,而不是使用Regex伪装它。

答案 1 :(得分:0)

这是我现在正在使用的代码:

def content_must_not_be_empty_string(tokens):
    if tokens[0]=="":
        raise ParseException("content cannot be empty")

text_no_start = Regex('<text[^<]*link="no"[^<]*>')
text_no_end = Regex('</text>[ \t\n\r\xa0]*')
text_no_content = SkipTo(text_no_start | text_no_end)
text_no_content.setParseAction(content_must_not_be_empty_string)
text_no = originalTextFor(nestedExpr(text_no_start,text_no_end,text_no_content), asString="False")
text_no.setParseAction(somemethod)