user2154324
user2154324

Reputation: 3

PHP nested if conditions

I'm using a template system. In this template system I am using the structure shown below for if-else conditions;

<if condition="'$condition' != 1">
    <div>true source</div>
</if>

than I'm separating the expression with the following pattern;

$pattern_case = '<if condition="(.*?)">(.*?)</if>';
preg_match("#$pattern_case#si",$string,$case)

but somecases if-else processes can be used one within the other (nested? - recusirve?) For example;

<if condition="'$condition1' != 1">
    <div>condition 1 text</div>
    <if condition="'$condition2' == 2 ">
        <div>condition 2 text</div>
    </if>
    condition 1 text more
</if>

In this cases pattern gives following results.

<if condition="'$condition1' != 1">
    <div>condition 1 text</div>
    <if condition="'$condition2' == 2 ">
        <div>condition 2 text</div>
    </if>

(so without this)

    condition 1 text more
</if>

Without using domdocument how can I solve that problem with regex ?

Upvotes: 0

Views: 413

Answers (2)

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89584

You can. "By design, regular expressions cannot deal with recursion." is true, but PCRE offers more features than a strict regular expression language. It's the reason why the term "regular expression" is inexact to refer to "regex" in many languages.

The way to do that:

$subject = <<<'LOD'
<if condition="'$condition1' != 1">
<div>condition 1 text</div>
<if condition="'$condition2' == 2 ">
<div>condition 2 text</div>
</if>
condition 1 text more
</if>
LOD;
$pattern = '~<if condition="(?<condition>[^"]+)">(?<content>(?:.*?(?R)?)+?)</if>~s';
preg_match_all( $pattern, $subject, $matches );
print_r($matches); // see your html source

This code match your nested structure. Now, the bad news: You can't capture "condition" and "content" from the other depths with a single pattern! A way to do that is to make a recursive function that retries the pattern on "content" and stops when there's no more nested "if".
For a replacement, you can also build a pattern that describes the innermost "if" tag (a pattern that forbids other nested "if") and apply it in a do..while loop.

Keep in mind that this approach has an high complexity (in the algorithmic sense) and that a better way is to use the DOM.

Upvotes: 0

mrks
mrks

Reputation: 8343

You can't. By design, regular expressions cannot deal with recursion.

For more information, you might want to read the first answer here: Can regular expressions be used to match nested patterns?

And yes, I know that some special "regular expressions" do allow for recursion. However, in most cases, this means that you are doing something horrible.

Upvotes: 1

Related Questions