Let's break down the regex vs the actual match so you can see why it matches:
(<Properties>).+?%%.+?%%.+?(<\/Properties>)
(<Properties>)
matches the first <Properties>
.
.+?
matches one or more characters until it encounters %%
, thus matching <Property>TEXT</Property><Properties><Property >
.
%%
matches %%
.
.+?
matches one or more characters until it encounters %%
, thus matching TEXT
.
%%
matches %%
.
.+?
matches one or more characters until it encounters </Properties>
thus matching </Property
.
(<\/Properties>)
matches </Properties>
.
Instead you want to make your regex more explicit:
(?:[^<%]|%(?!%)|<(?!\/Properties>))
The above will match one character that is not <
or %
, if it is one of those two it will only match %
if not followed by another %
and it will only match <
if not followed by /Properties>
. This should be used as replacement for your .
. Resulting in:
(<Properties>)(?:[^<%]|%(?!%)|<(?!\/Properties>))+%%(?:[^<%]|%(?!%)|<(?!\/Properties>))+%%(?:[^<%]|%(?!%)|<(?!\/Properties>))+(<\/Properties>)
Since the regex is more explicit I can remove the lazy ?
quantifier modifier safely.