using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
{
public class UniversalSubtitleFormat : SubtitleFormat
{
public override string Extension => ".usf";
public override string Name => "Universal Subtitle Format";
public override string ToText(Subtitle subtitle, string title)
{
string xmlStructure =
"" + Environment.NewLine +
"" + Environment.NewLine +
@"
Universal Subtitle Format
SubtitleEdit
nikse.dk@gmail.com
http://www.nikse.dk/
" + Environment.NewLine +
" English" + Environment.NewLine +
@" [DATE]
This is a USF file
" + Environment.NewLine +
"
";
xmlStructure = xmlStructure.Replace("[DATE]", DateTime.Now.ToString("yyyy-MM-dd"));
var xml = new XmlDocument();
xml.LoadXml(xmlStructure);
xml.DocumentElement.SelectSingleNode("metadata/title").InnerText = title;
var subtitlesNode = xml.DocumentElement.SelectSingleNode("subtitles");
foreach (Paragraph p in subtitle.Paragraphs)
{
XmlNode paragraph = xml.CreateElement("subtitle");
XmlAttribute start = xml.CreateAttribute("start");
start.InnerText = p.StartTime.ToString().Replace(",", ".");
paragraph.Attributes.Prepend(start);
XmlAttribute stop = xml.CreateAttribute("stop");
stop.InnerText = p.EndTime.ToString().Replace(",", ".");
paragraph.Attributes.Append(stop);
XmlNode text = xml.CreateElement("text");
bool first = true;
foreach (string line in HtmlUtil.RemoveHtmlTags(p.Text, true).SplitToLines())
{
if (!first)
{
XmlNode br = xml.CreateElement("br");
text.AppendChild(br);
}
first = false;
var t = xml.CreateTextNode(string.Empty);
t.InnerText = line;
text.AppendChild(t);
}
paragraph.AppendChild(text);
XmlAttribute style = xml.CreateAttribute("style");
style.InnerText = "Default";
text.Attributes.Append(style);
subtitlesNode.AppendChild(paragraph);
}
return ToUtf8XmlString(xml);
}
private static TimeCode DecodeTimeCode(string code)
{
string[] parts = code.Split(new[] { ':', '.', ',' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 1)
{
return new TimeCode(0, 0, int.Parse(code), 0); // seconds only
}
if (parts.Length == 2)
{
return new TimeCode(0, 0, int.Parse(parts[0]), int.Parse(parts[1])); // seconds + ms
}
//00:00:07:120
string hour = parts[0];
string minutes = parts[1];
string seconds = parts[2];
string ms = parts[3];
return new TimeCode(int.Parse(hour), int.Parse(minutes), int.Parse(seconds), int.Parse(ms));
}
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(""))
return;
var xml = new XmlDocument { XmlResolver = null };
try
{
xml.LoadXml(xmlString);
}
catch
{
_errorCount = 1;
return;
}
foreach (XmlNode node in xml.DocumentElement.SelectNodes("subtitles/subtitle"))
{
try
{
string start = node.Attributes["start"].InnerText;
string stop = node.Attributes["stop"].InnerText;
var text = new StringBuilder();
foreach (XmlNode innerNode in node.SelectSingleNode("text").ChildNodes)
{
switch (innerNode.Name.Replace("tt:", string.Empty))
{
case "br":
text.AppendLine();
break;
default:
text.Append(innerNode.InnerText);
break;
}
}
subtitle.Paragraphs.Add(new Paragraph(DecodeTimeCode(start), DecodeTimeCode(stop), text.ToString().Trim()));
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
_errorCount++;
}
}
subtitle.Renumber();
}
}
}