Reputation: 3
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
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
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