tags:

views:

43

answers:

4

I need to replace <slot> slot_name </slot> with a <?php !include_slot('slot_name')?> in the text that I read from file

<table class="layout-table" id="layout1">
    <tr>
        <td class="slot" id="slot1" colspan="2">
            <slot>
                slot_name
            </slot>
        </td>
    </tr>
    <tr>
        <td class="slot" id="slot2" rowspan="2">
            <slot>
                slot_name
            </slot>        
       </td>
        <td class="slot" id="slot3">
            <slot>
                slot_name
            </slot>
        </td>
    </tr>
</table>

could anybody give me some directions as I had not really worked with this kind of traversing before. The problem is to iterate through the text and at the same time change the block with respect to the "slot_name"

A: 

Use a DOM-based XML parser. See today's topic du jour, http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html .

Borealid
A: 

An XML parser can do the job. You can also do it the dirty way with a str_replace or a regular expression.

Stegeman
Can you give a a little description in terms of steps, As I have a clear view how to replace all the occurring blocks, but the issue is with the "slot_name" I have to do it with respect to it , and slot_name is gonna be different for each time. thanks
simple
A: 

If the markup is as simple as that, and it'll only ever be <slot>[Whitespace]slot_name[Whitespace]</slot> then a regular expression will be absolutely fine, and an XML parser will be overkill.

If you want to learn regex, go to Regular-Expressions.info.

If you find yourself adding more and more functionality, and it stops being as simple as the skeleton outlined above, then by all means start using a proper parser. Otherwise, do the simplest thing that could possibly work.

Skilldrick
+2  A: 

Since you appear to be doing a straight search-and-replace, and not actually parsing HTML or XML, doing a regex here is a perfectly valid option.
(If you might have existing PHP containing this slot stuff, or otherwise start getting into nested tags, commenting, and similar, you'll be wanting to use a DOM parser.)

This one uses lookahead/lookbehind to mean that the whole match is slot_name:

(?<=<slot>\s*)\w+(?=\s*</slot>)

Alternatively, this will place the slot_name into capture group 1:

<slot>\s*(\w+)\s*</slot>


(These both assume that slot_name is comprised of "word characters", which is alphanumerics and underscore.)

Explanation of the first one is:

(?<=        # begin positive lookbehind
    <slot>   # literal text
    \s*      # zero or more whitespace
)           # end positive lookbehind
\w+         # one or more word characters
(?=         # begin positive lookahead
    \s*      # zero or more whitespace
    </slot>  # literal text
)           # end positive lookahead

The second lacks the lookaheads, but uses simple cature group syntax (...) but is otherwise no new syntax.

(If you do want to learn regular expressions fully, regular-expressions.info has a tutorial worth completing.)

So yeah, either one of these lines will do it:

preg_replace( "/(?<=<slot>\s*)\w+(?=\s*<\/slot>)/" , "<?php !include_slot('$0')?>" , $Input )
preg_replace( "/<slot>(\w+)\s*<\/slot>/" , "<?php !include_slot('$1')?>" , $Input )

(Note the escaped forward slashes - alternatively you can use different characters at the start/end to delimit the regex.)

Peter Boughton
Yes, I'd usually use pipes to delimit a regex like this. Why would you use lookarounds instead of a simple capturing group? Not trolling, just out of interest.
Skilldrick
Well, primarily because lookarounds are closer to the intent of what is being done - "find X that is prefixed by A and suffixed by B". But also, it's good to show different options - to increase people's exposure and give them ideas for other situations. And of course to remind people that `$0` exists, since a lot forget (or never learn) that. :)
Peter Boughton