在嵌套大括号内添加自己的文本 + 异常

add own text inside nested braces + exception

原题位于,本题是想回避一个问题

我有这段代码可以与 html_1 数据完美配合:

from pyparsing import nestedExpr, originalTextFor

html_1 = '''
<html>
<head>
<title><?php echo "title here"; ?></title>
<head>
    <body>
        <h1 <?php echo "class='big'" ?>>foo</h1>
    </body>
</html>
'''

html_2 = '''
<html>
<head>
<title><?php echo "title here"; ?></title>
<head>
    <body>
        <h1 <?php echo $tpl->showStyle(); ?>>foo</h1>
    </body>
</html>
'''

nested_angle_braces = nestedExpr('<', '>')

# for match in nested_angle_braces.searchString(html):
#     print(match)

# nested_angle_braces_with_h1 = nested_angle_braces().addCondition(
#                                             lambda tokens: tokens[0][0].lower() == 'h1')

nested_angle_braces_with_h1 = originalTextFor(
    nested_angle_braces().addCondition(lambda tokens: tokens[0][0].lower() == 'h1')
    )
nested_angle_braces_with_h1.addParseAction(lambda tokens: tokens[0] + 'MY_TEXT')

print(nested_angle_braces_with_h1.transformString(html_1))

html_1 变量的结果是:

<html>
<head>
<title><?php echo "title here"; ?></title>
<head>
    <body>
        <h1 <?php echo "class='big'" ?>>MY_TEXTfoo</h1>
    </body>
</html>

到这里就可以了,都按预期放置了。 MY_TEXT 位于右侧区域(在 h1 标签内)。

但让我们看看 html_2 的结果:

<html>
<head>
<title><?php echo "title here"; ?></title>
<head>
    <body>
        <h1 <?php echo $tpl->showStyle(); ?>MY_TEXT>foo</h1>
    </body>
</html>

现在我们得到错误,MY_TEXT 放置在 h1 属性 区域内,因为 PHP 在“$tpl->”中包含大括号。

我该如何解决?我需要在那个地区得到这个结果:

<h1 <?php echo $tpl->showStyle(); ?>>MY_TEXTfoo</h1>

解决方案要求我们为 PHP 标签定义一个特殊的表达式,我们简单的 nestedExpr 会被它混淆。

# define an expression for a PHP tag
php_tag = Literal('<?') + 'php' + SkipTo('?>', include=True)

我们现在需要的不仅仅是用于开场白和闭幕词的简单字符串,包括在匹配“<”以确保我们不在 PHP 标签的前缘时的否定前瞻:

# define expressions for opener and closer, such that  we don't 
# accidentally interpret a PHP tag as a nested  expr
opener = ~php_tag + Literal("<")
closer = Literal(">")

如果opener 和closer 不是简单的字符串,那么我们也需要给出一个内容表达式。我们的内容定义起来非常简单,只是 PHP 标签或其他可打印的单词,不包括“<”和“>”(无论如何你最终都会将它们全部包装在 originalTextFor 中):

# define nested_angle_braces to potentially contain PHP tag, or 
# some other printable (not including '<' or '>' chars)
nested_angle_braces = nestedExpr(opener, closer, 
                                 content=php_tag | Word(printables, excludeChars="<>"))

现在如果我使用 nested_angle_braces.searchString 扫描 html_2,我得到:

for tag in originalTextFor(nested_angle_braces).searchString(html_2):
    print(tag)

['<html>']
['<head>']
['<title>']
['</title>']
['<head>']
['<body>']
['<h1 <?php echo $tpl->showStyle(); ?>>']
['</h1>']
['</body>']
['</html>']