I have some XML that I want to replace.
Below, I want to replace "Alarm"
within <Alarm name="Alarm">
with the name
of the Tag
to which it belongs.
E.g. for the first Tag
below, the Tag
name
is "Buffer Tank Pig Catcher Equipment Fault"
So the Alarm
name
would need to be set to "Buffer Tank Pig Catcher Equipment Fault" as well. I plan to use notepad++, so I need to use capture groups in order to put it all back together.
I have a regex saved on regexr: regexr.com/58ac5
(<Tag name=)("[\w\d\s]+")( path="Alarms"[\w\d\s=">\r\n</\-;\[{}\]!@#$%^&*+(),\.]+<Alarm name=)("[\w\d\s]+")
But it's not returning the right results. It captures the correct start, but it matches up until the very last Tag's <Alarm name="..."
in the XML (if you add more than two of the tag elements you'll see that it gets to the last Tag element before finding the <Alarm name="..." part and ending the capture). It's not capturing each Tag individually.
So my question is, how can I capture the text in between the two text blocks (e.g. <Tag name="Tag Name" path="Alarms"
and <Alarm name="Alarm"
) for each Tag element?
(what should this part be replace with? [\w\d\s=">\r\n</\-;\[{}\]!@#$%^&*+(),\.]+
)
Thanks in advance!
<Tag name="Buffer Tank Pig Catcher Equipment Fault" path="Alarms" type="OPC">
<Property name="Value"/>
<Property name="DataType">6</Property>
<Property name="OPCServer">Ignition OPC-UA Server</Property>
<Property name="OPCItemPath">ns=1;s=[{PLCName}]{DeviceName}_Trfer.Alm.11</Property>
<Property name="EngUnit">%</Property>
<Property name="PrimaryHistoryProvider">SQLServer</Property>
<Property name="HistoryMaxAgeMode">5</Property>
<Property name="HistoryMaxAge">4</Property>
<Alarms>
<Alarm name="Alarm">
<Property name="setpointA">1</Property>
<Property name="priority">3</Property>
<Property name="ackMode">1</Property>
<Property name="label" bindtype="Expression">'{InstanceName} {TagName}'</Property>
<Property name="displayPath" bindtype="Expression">replace(replace(replace(
{itemPath}
,{System/Site Name} + '/', '')
,'/Alarms/', '/')
,'/',' ')</Property>
</Alarm>
</Alarms>
</Tag>
<Tag name="Low Flow Alarm" path="Alarms" type="OPC">
<Property name="Value"/>
<Property name="DataType">6</Property>
<Property name="OPCServer">Ignition OPC-UA Server</Property>
<Property name="OPCItemPath">ns=1;s=[{PLCName}]{DeviceName}_Trfer.Alm.15</Property>
<Property name="EngUnit">%</Property>
<Property name="PrimaryHistoryProvider">SQLServer</Property>
<Property name="HistoryMaxAgeMode">5</Property>
<Property name="HistoryMaxAge">4</Property>
<Alarms>
<Alarm name="Alarm">
<Property name="setpointA">1</Property>
<Property name="ackMode">1</Property>
<Property name="label" bindtype="Expression">'{InstanceName} {TagName}'</Property>
<Property name="displayPath" bindtype="Expression">replace(replace(replace(
{itemPath}
,{System/Site Name} + '/', '')
,'/Alarms/', '/')
,'/',' ')</Property>
</Alarm>
</Alarms>
Update:
I found a situation where this doesn't quite work, if there are <Tags>
that don't have an <Alarm>
element, it keeps returning until it finds a <Alarm>
element within another <Tag>
. So it could have multiple finds of <Tag>
elements which is incorrect. Basically I don't want it to return the purpley-blue highlighted section below:
https://regexr.com/58pi5
I need to discard the find if it encounters a closing </Tag>
element before it finds the <Alarm..>
element. I've tried negative lookbehind/ahead, and can't get it working..