public static List<Run> GetSpanRuns(string source)
 {
     string[] parts = spanRegex.Split(source);
     var result = new List<Run>();
     foreach (string part in parts)
     {
         Run run = new Run();
         run.Content = null;
         run.Lang = null;
         run.StyleName = null;
         run.Guid = null;
         Match match = spanContentsRegex.Match(part);
         if (!match.Success || match.Groups.Count < 8 || !match.Groups["spanText"].Success)
         {
             // We're outside a span
             run.Content = part;
             result.Add(run);
             continue;
         }
         // We're inside a span
         run.Content = match.Groups["spanText"].Value;
         if (match.Groups["langAttr1"].Success && match.Groups["langText1"].Success)
             run.Lang = match.Groups["langText1"].Value;
         else if (match.Groups["langAttr2"].Success && match.Groups["langText2"].Success)
             run.Lang = match.Groups["langText2"].Value;
         if (match.Groups["classAttr"].Success && match.Groups["classText"].Success)
         {
             string[] classes = match.Groups["classText"].Value.Split(null);  // Split on any whitespace
             foreach (string cls in classes)
             {
                 Match m = styleRegex.Match(cls);
                 if (m.Success && m.Groups[1].Success)
                     run.StyleName = m.Groups[1].Value.Replace("_SPACE_", " ");
                 Guid g;
                 m = guidRegex.Match(cls);
                 if (m.Success && m.Groups[1].Success && Guid.TryParse(m.Groups[1].Value, out g))
                     run.Guid = g;
                 m = intPropRegex.Match(cls);
                 if (m.Success && m.Groups["propNum"].Success && m.Groups["propValue"].Success && m.Groups["propVariation"].Success)
                 {
                     if (run.IntProperties == null)
                         run.IntProperties = new Dictionary<int, IntProperty>();
                     int propNum;
                     int propValue;
                     int propVariation;
                     if (Int32.TryParse(m.Groups["propNum"].Value, out propNum) &&
                         Int32.TryParse(m.Groups["propValue"].Value, out propValue) &&
                         Int32.TryParse(m.Groups["propVariation"].Value, out propVariation))
                     {
                         run.IntProperties[propNum] = new IntProperty(propValue, propVariation);
                     }
                 }
                 m = strPropRegex.Match(cls);
                 if (m.Success && m.Groups["propNum"].Success && m.Groups["propValue"].Success)
                 {
                     if (run.StringProperties == null)
                         run.StringProperties = new Dictionary<int, string>();
                     int propNum;
                     if (Int32.TryParse(m.Groups["propNum"].Value, out propNum))
                         run.StringProperties[propNum] = m.Groups["propValue"].Value.Replace("_SPACE_", " ");
                 }
             }
         }
         result.Add(run);
     }
     return result;
 }
 public static bool RunWasSpan(Run run)
 {
     return run.Lang != null || run.StyleName != null || run.Guid != null;
 }