0

For example, i have something like this:

<i id="text">text</i><br><i>text2</i>

and I want to change it to something like this:

<b>text</b><br><i>text2</i>

so it will keep the <i>text2</i>

but change the <i id="text">text</i> into <b>text</b>

is that even possible?

Ninjiangstar
  • 225
  • 1
  • 3
  • 12
  • 3
    Absolutely, using regular expressions. Sorry I can't be of much further help - I hate writing them! Just thought I'd chip in with where to start looking. – Andy Hunt Aug 11 '11 at 09:01
  • 1
    the complexity of code depends on the variance of your input data. Can you show more input examples? – Raptor Aug 11 '11 at 09:03
  • 1
    @AndyBursh Well, not so fast... are HTML comments, CDATA sections, and other inline elements and PHP sections and other things allowed inside the `i` element? If so, then use an HTML parser.... – Ray Toal Aug 11 '11 at 09:06
  • @Ray you have a point! I'm taking the examples provided as gospel as it stands; though I'd agree if you said that's maybe not a great idea. – Andy Hunt Aug 11 '11 at 09:09
  • @Ray HTML parser? Does PHP have one? If you mean XML parser then it will choke on OP's example because of that `
    ` without the ending tag.
    – nobody Aug 11 '11 at 09:15
  • @AndyBursh thanks a lot i just didn't know what to search for. that gave me a great boost – Ninjiangstar Aug 11 '11 at 09:17
  • @nobody, you are right that an XML parser would choke on the OP's post but there is no reason why an HTML parser could not be written; it is just a little more complicated than one for XML. I was only trying to point out, without linking to http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags that if the `i` tag was very complex (e.g. has arbitrary nesting) than a simple regex will not work. – Ray Toal Aug 11 '11 at 09:22

2 Answers2

3

Assuming there are no nested <i> tags, this should do the trick:

Input regular expression: <i id=".*?">(.*?)</i>

Replacement: <b>\1</b>

$output = preg_replace('/<i id=".*?">(.*?)<\/i>/i', '<b>\1</b>', $input);

Untested, but it should work.

user703016
  • 37,307
  • 8
  • 87
  • 112
  • Watch out for the `/i` inside the regex delimited by slashes. – Ray Toal Aug 11 '11 at 09:12
  • Great now double up the backslashes because they are in php strings. Otherwise you get "Unknown modifier '>' :) – Ray Toal Aug 11 '11 at 09:18
  • @Ray: um... no, why would that happen? – user703016 Aug 11 '11 at 09:21
  • Oops, I blindly put the following into http://writecodeonline.com/php/: `$input = 'text
    text2'; $output = preg_replace('/(.*?)<\/i>/i', '\1', $input); echo $output;` and got the error. If you are not iterpreting the code then what you have is good. +1
    – Ray Toal Aug 11 '11 at 09:25
  • thanks! this helped a lot! however this made everything load incredibly slowly (i actually intended to do this on links, but i thought my link example won't make sense) because there was like 400 links or so – Ninjiangstar Aug 11 '11 at 09:42
0

This recursive regex works with any levels of nesting:

function regReplace( $str ) {
    return preg_replace_callback( '/<i id="text">(.*?(?R)*)<\/i>/is', 'replaceTags', $str );
}

function replaceTags( $matches ) {
    return '<b>'.regReplace( $matches[1] ).'</b>';
}

var_dump( regReplace( '<i id="text">text <i id="text">text <i id="text">text</i></i></i><br><i>text2</i>' ) );

result:

<b>text <b>text <b>text</b></b></b><br><i>text2</i>
nobody
  • 10,599
  • 4
  • 26
  • 43