UltraEdit macro to select HTML/XML tag
Update Sunday 19 April 2015, 12:06:27 AM: this post has been superseded by a new one: UltraEdit macro to select HTML/XML tag (same name, very different content).
Editing HTML or XML in UltraEdit is now just a little bit easier for me with this macro that incrementally selects HTML/XML elements.
Thanks to Bulgrien in my UltraEdit forum post “macro to select HTML tag” the base case macro to select tag start to finish is very simple. Consider the text below. I wanted a macro to select the DIV
and its contents (including the DIV tag itself).
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
Here is a very simple macro that will do that.
InsertMode ColumnModeOff HexOff Find Select "</^s>" Find Up Select "<"
The ^s
means “selected text”. To use this macro on the example text, double click the first DIV token and run the macro. Unfortunately, this macro is not so useful if the element contains nested elements with the same tag name, such as in the example below. If you double click on the first DIV token in the text below and run the macro, it will select only to the first DIV close (as the coloured text shows).
<DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
</DIV>
AFAIK UltraEdit’s macro language doesn’t have the logic structures to repeat through nested tags (recursion or looping and arithmetic) - let alone deal with broken nested tags. I could write a Javascript to do this, but I don’t want to invest the time to get it right. So my compromise is to put the decision logic in the hands of a human operator. (Probably for the best; wouldn’t want SkyNet) to start with a run-away UltraEdit macro.)
Here is the new and improved macro.
InsertMode ColumnModeOff HexOff UltraEditReOn IfSel Find RegExp Select "</++^c>++" Else SelectWord Copy Find Select "</^c>" Find Up Select "<" EndIf
To use it, put the cursor in the first DIV (don’t select it or copy it) and run the macro. It will still select only to the first close tag, but each time you re-run the macro (control+m) it will expand the selection to the next tag opening or closing. This way, you can count for yourself how many nested tags there are and stop when you need to.
First run:
<DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
</DIV>
Second run (control+m):
<DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
</DIV>
Third run (control+m):
<DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
</DIV>
Fourth run (control+m):
<DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
<DIV style="...">abc <SPAN>def</SPAN> ghi.</DIV>
</DIV>
And to do the same thing the other way, use this one.
InsertMode ColumnModeOff HexOff UltraEditReOn IfSel Find RegExp Up Select "</++^c>++" Else SelectWord Copy Find Up Select "</^c>" Find Select ">" EndIf
Personally, I have the select forward macro mapped to Control+Shift+.
and the select backwards macro mapped to Control+Shift+,
Notes.
- A very simple Perl regex will do almost the same thing as Bulgrien’s macro above:
<DIV[^>]*>([^ÿ]*?)</DIV>
. Unfortunately you can’t use^s
in regular expressions though.