using System; using System.Collections.Generic; using System.Globalization; using System.Text; using System.Xml; namespace Nikse.SubtitleEdit.Core.SubtitleFormats { public class CaptionateMs : SubtitleFormat { public override string Extension { get { return ".xml"; } } public override string Name { get { return "Captionate MS"; } } public override bool IsTimeBased { get { return true; } } public override bool IsMine(List lines, string fileName) { var subtitle = new Subtitle(); LoadSubtitle(subtitle, lines, fileName); return subtitle.Paragraphs.Count > 0; } public override string ToText(Subtitle subtitle, string title) { const string xmlStructure = @" ms namesareprefixed Default 140 "; var xml = new XmlDocument(); xml.LoadXml(xmlStructure); Paragraph last = null; foreach (Paragraph p in subtitle.Paragraphs) { if (last != null) { if (last.EndTime.TotalMilliseconds + 500 < p.StartTime.TotalMilliseconds) { var blank = new Paragraph { StartTime = { TotalMilliseconds = last.EndTime.TotalMilliseconds } }; AddParagraph(xml, blank); } } AddParagraph(xml, p); last = p; } return ToUtf8XmlString(xml, true); } private static void AddParagraph(XmlDocument xml, Paragraph p) { XmlNode paragraph = xml.CreateElement("caption"); XmlAttribute start = xml.CreateAttribute("time"); start.InnerText = EncodeTime(p.StartTime); paragraph.Attributes.Append(start); if (!string.IsNullOrWhiteSpace(p.Text)) { XmlNode tracks = xml.CreateElement("tracks"); paragraph.AppendChild(tracks); XmlNode track0 = xml.CreateElement("track0"); track0.InnerText = HtmlUtil.RemoveHtmlTags(p.Text, true); track0.InnerXml = track0.InnerXml.Replace(Environment.NewLine, "
"); tracks.AppendChild(track0); } xml.DocumentElement.SelectSingleNode("captions").AppendChild(paragraph); } public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName) { _errorCount = 0; var sb = new StringBuilder(); lines.ForEach(line => sb.AppendLine(line)); string xmlString = sb.ToString(); if (!xmlString.Contains("") || !xmlString.Contains("")) return; var xml = new XmlDocument { XmlResolver = null }; try { xml.LoadXml(xmlString); } catch { _errorCount = 1; return; } Paragraph p = null; foreach (XmlNode node in xml.DocumentElement.SelectNodes("captions/caption")) { try { if (node.Attributes["time"] != null) { string start = node.Attributes["time"].InnerText; double startMilliseconds = double.Parse(start); if (p != null) p.EndTime.TotalMilliseconds = startMilliseconds - 1; if (node.SelectSingleNode("tracks/track0") != null) { string text = node.SelectSingleNode("tracks/track0").InnerText; text = HtmlUtil.RemoveHtmlTags(text); text = text.Replace("
", Environment.NewLine).Replace("
", Environment.NewLine).Replace("
", Environment.NewLine); p = new Paragraph(text, startMilliseconds, startMilliseconds + 3000); if (!string.IsNullOrWhiteSpace(text)) subtitle.Paragraphs.Add(p); } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); _errorCount++; } } subtitle.Renumber(); } private static string EncodeTime(TimeCode time) { return time.TotalMilliseconds.ToString(CultureInfo.InvariantCulture); } } }