1

How can I replace:

<tag attr="z">
    <tag attr="y">
        <tag attr="x"></tag>
    </tag>
</tag>

to:

<tag attr="z">
    [tag=y]
        <tag attr="x"></tag>
    [/tag]
</tag>

Without using extensions?

I unsuccessfully tried:

preg_replace("#<tag attr=\"y\">(.+?)</tag>#i", "[tag=y]\\1[/tag]", $text);
2
  • preg_replace("#<tag attr=\"y\">(.+?)</tag>#i", "[tag=y]\\1[/tag]", $text); Commented Sep 3, 2012 at 13:33
  • Click "edit" to update your question with more information, this is easier to read than the comments. Commented Sep 3, 2012 at 16:54

1 Answer 1

2

Well, PHP's regex implementation supports PCRE's recursive patterns. However, I'd hesitate to use such a feature because of its cryptic nature. However, since you asked:

Without using extensions?

here it is:

<?php

$html = '<tag attr="z">
    <tag attr="y">
        <tag>
            <tag attr="more" stuff="here">
                <tag attr="x"></tag>
            </tag>
        </tag>
    </tag>
</tag>
';

$attr_regex = "(?:\s+\w+\s*=\s*(?:'[^']*'|\"[^\"]*\"))";
$recursive_regex = "@
    <tag\s+attr=\"y\">         # match opening tag with attribute 'y'
    (                          # start match group 1
      \s*                      #   match zero or more white-space chars
      <(\w+)$attr_regex*\\s*>  #   match an opening tag and store the name in group 2
      (                        #   start match group 3
        [^<]+                  #     match one or more chars other than '<'
        |                      #     OR
        (?1)                   #     match whatever the pattern from match group 1 matches (recursive call!)
      )*                       #   end match group 3
      </\\2>                   #   match the closing tag with the same name stored in group 2
      \s*                      #   match zero or more white-space chars
    )                          # end match group 1
    </tag>                     # match closing tag
    @x";

echo preg_replace($recursive_regex, "[tag=y]$1[/tag]", $html);

?>

which will print the following:

<tag attr="z">
    [tag=y]
        <tag>
            <tag attr="more" stuff="here">
                <tag attr="x"></tag>
            </tag>
        </tag>
    [/tag]
</tag>
Sign up to request clarification or add additional context in comments.

3 Comments

Why can't I run this Regex Code twice?
@Bestudio, you can. Perhaps create another question ?
@Bestudio, sorry, I don't know what you mean. I don't know what you meant by "running it twice" and I don't know what you mean by "having an example". As you can see from my answer, the regex works just fine, and my code snippet is self-contained: you can run it and see that it works. If you have another problem, I suggest you create another question for it (as I suggested earlier). Good luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.