Replace text between tag only if specified text appears in parent tag
-
I might not have used the correct term tag but this is what I have and what I want to achieve.
I have an xml file that contains blocks like this:
<game name="3 in 1 College & Pro Football (Disk 1)" index="true" image="3"> <description>3 in 1 College & Pro Football (Disk 1)</description> <manufacturer>Lance Haffner Games</manufacturer> <cloneof/> <crc>C0C68997</crc> <year>1985</year> <genre>Sports/Football</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game> <game name="3 in 1 College & Pro Football (Disk 2) (Utilities)" index="" image=""> <description>3 in 1 College & Pro Football (Disk 2) (Utilities)</description> <manufacturer>Lance Haffner Games</manufacturer> <cloneof/> <crc>18249FAD</crc> <year>1985</year> <genre>Sports/Football</genre> <rating>HSRS - GA (General Audience)</rating> <enabled>Yes</enabled> </game>
What I would like to do is whenever (Disk 2) appears in the game tag, change the enabled tag from Yes to No
I don’t know how to get the search to treat each set of <game> </game> tags as separate from each other.
Thank you.
-
Hello, Paul Flint,
No problem with the right regular expression ! So, the problem can be split in three steps :
-
Go the next name tag, which value contains the string Disk 2
-
Then move, downwards, to the enabled tag of the current game node, in order to catch its Yes value
-
Change that value of the enabled tag, from Yes to No
The first two steps can be achieved with a search regular expression and the third step with the replacement regular expression !
So, follow these few steps, below :
-
First, move back to the very beginning of your XML file ( Ctrl + Home )
-
Open the Replace dialog ( Ctrl + H )
-
Select the Regular expression search mode
-
Fill up the two fields Find what: and Replace with:, with the expressions, below :
SEARCH
((?-s)<game.+Disk 2(?s).+?)Yes(?=</enabled>)
REPLACE
\1No
- Click on the Replace all button
Et voilà !
NOTES :
-
The part
(?-s)<game.+Disk 2
looks for the string <game, followed by any, NON-empty, range of standard characters ( due to the(?-s)
modifier ), ending with the string Disk 2 -
The part
(?s).+?
, then, looks for the shortest range of ANY character ( standard or EOL ) ( due to the(?s)
modifier )…, till a first string Yes. Note that this range of characters will always be a multi-lines block ! -
The part
Yes(?=</enabled>)
, finally, searches for the string Yes, but ONLY IF this string is followed by the expression </enabled>. If you’re sure that, nowhere else, the Yes string may occur, the positive look-around(?=</enabled>)
is not needed ! -
As two parentheses surround the regex expression
(?-s)<game.+Disk 2(?s).+?
, that means that all text between <game name and <enabled>, just before the string Yes, is stored as group 1 -
In replacement, all that text is just rewritten, due to
\1
, and the matched Yes value is, simply, changed into the No value
Remarks :
- I suppose that your search is case SENSITIVE. If, for instance, the string disk 2 and/or the value yes may occur, just add the
(?i)
, at beginning of the present search regex, as below, to force the regex engine to perform the search in an INSENSITIVE way :
(?i)((?-s)<game.+Disk 2(?s).+?)Yes(?=</enabled>)
-
Note, also, that the different in-line modifiers, in regexes, have higher priority than their associate options, in the Find dialog. So, for instance :
-
The regex
(?i)AbC
would look for the string abc, in ANY case, even if you, previously, checked the Match case option -
The regex
(?-s)A.+Z
would look for the longest one-line string , beginning with letter A and ending with letter Z, even if you, previously, checked the . matches newline option
-
-
An other form of that S/R, using the
\K
syntax, in the search regex, is :
SEARCH
(?-s)<game.+Disk 2(?s).+?\KYes(?=</enabled>)
REPLACE
No
-
-
Like above, the regex engine matches from the string <game… ( which contains the Disk 2 string ), till the string <enabled>, but, when meeting the
\K
form, forgets this match and resets the character position of search to the location just before the Yes value -
Therefore, it just matches the string Yes, ONLY IF followed by the string </enabled> and changes it with the No value
-
IMPORTANT : Due to the
\K
syntax, you cannot do replacement step by step, with the Replace button. You must use, EXCLUSIVELY, the Replace All button !
-
Best Regards,
guy038
-
-
Thank you for your help.