The only problems I had doing replacements of variables in WordML documents where caused by the spelling and grammar module which tend to insert special tags which breaks your variable names which is solved by deactivating completely checking and marking of grammar errors in Word during template editing.
My method of replacing is something like this (my convention for naming variables is a little different, this one is addapted to yours):
public static void Assign(XElement xe, string name, string value)
{
XElement el = xe.Descendants()
.FirstOrDefault(e => e.Name.LocalName == "t" && e.Value.Contains("(@" + name + ")"));
if (el != null)
{
el.Value = el.Value.Replace("(@" + name + ")", value);
}
else
{
AssignFallback(xe, name, value);
}
}
EDIT 2
I wrote a fallback method of replacing the variable in case the above don't work (case el == null) above. A paragraph w:p can contain multiple runs and our variable name could be breaked across a continuous serie of runs. So we want to identify those and replace the value only in first, removing the rest. We have to be carefull to preserve the text wich could appear before de variable name and after (prefix will be in the first run and sufix in the last one).
public static void AssignFallback(XElement xe, string name, string value)
{
string varName = "(@" + name + ")";
XElement xep = xe.Descendants()
.FirstOrDefault(x => x.Name.LocalName == "p" && x.Value.Contains(varName));
if (xep == null)
{
return;
}
string prefix = "", sufix = "";
List<XElement> truns = new List<XElement>();
List<XElement> allruns = xep.Descendants().Where(x => x.Name.LocalName == "r").ToList();
for (int i = 0; i < allruns.Count; i++)
{
if (!allruns[i].Value.Contains("(@"))
{
continue;
}
int index = allruns[i].Value.IndexOf("(@");
prefix = allruns[i].Value.Substring(0, index);
truns.Clear();
truns.Add(allruns[i]);
string nameTemp = allruns[i].Value.Substring(index, allruns[i].Value.Length - index);
if (!varName.StartsWith(nameTemp))
{
continue;
}
for (int j = i + 1; j < allruns.Count; j++)
{
nameTemp += allruns[j].Value;
truns.Add(allruns[j]);
if (nameTemp.StartsWith(varName))
{
sufix = nameTemp.Substring(varName.Length);
break;
}
else if (nameTemp.Length > varName.Length)
{
break;
}
}
if (nameTemp.StartsWith(varName))
{
XElement xet = truns[0].Descendants().FirstOrDefault(x => x.Name.LocalName == "t");
xet.Value = prefix + value + sufix;
for (int j = 1; j < truns.Count; j++)
{
truns[j].Remove();
}
}
}
}