求助:使用Linq将XML字幕转换为.srt纯文本时无法获取所有w节点值
解决LINQ解析XML字幕转SRT时无法获取所有节点的问题
我来帮你搞定这个LINQ解析XML字幕转SRT的问题!首先咱们先明确场景,假设你的XML字幕结构是类似这样的(常见的带
<subtitles> <p begin="00:00:01.000" end="00:00:04.000"> <w begin="00:00:01.000" end="00:00:02.000">Hello</w> <w begin="00:00:02.000" end="00:00:03.000">world</w> <w begin="00:00:03.000" end="00:00:04.000">!</w> </p> <p begin="00:00:05.000" end="00:00:07.000"> <w begin="00:00:05.000" end="00:00:06.000">This</w> <w begin="00:00:06.000" end="00:00:07.000">is</w> <w begin="00:00:07.000" end="00:00:08.000">a test</w> </p> </subtitles>
预期的SRT输出应该是这样的:
1 00:00:01,000 --> 00:00:04,000 Hello world ! 2 00:00:05,000 --> 00:00:08,000 This is a test
常见问题原因
你之前没获取到所有First()/Single()),或者没正确遍历<p>节点下的所有子
修正后的LINQ实现代码
下面是完整的C#代码,用LINQ to XML来完成转换,确保能拿到所有
using System; using System.IO; using System.Linq; using System.Xml.Linq; using System.Text; class XmlToSrtConverter { static void Main(string[] args) { // 1. 加载XML字幕文件 XDocument xmlSubtitles = XDocument.Load("your-input-subtitle.xml"); // 2. 用LINQ处理每个字幕段落,生成SRT条目 var srtEntries = xmlSubtitles.Descendants("p") .Select((paragraph, index) => new { // SRT的序号从1开始 SequenceNumber = index + 1, // 转换时间格式:把XML的.换成SRT的, StartTime = paragraph.Attribute("begin").Value.Replace('.', ','), // 取当前段落最后一个<w>的结束时间作为整个段落的结束时间 EndTime = paragraph.Descendants("w").Last().Attribute("end").Value.Replace('.', ','), // 拼接所有<w>的文本,用空格分隔 SubtitleText = string.Join(" ", paragraph.Descendants("w").Select(w => w.Value.Trim())) }); // 3. 拼接成完整的SRT内容 string fullSrtContent = string.Join(Environment.NewLine + Environment.NewLine, srtEntries.Select(entry => $"{entry.SequenceNumber}{Environment.NewLine}{entry.StartTime} --> {entry.EndTime}{Environment.NewLine}{entry.SubtitleText}")); // 4. 写入到SRT文件 File.WriteAllText("output-subtitle.srt", fullSrtContent, Encoding.UTF8); } }
关键细节说明
Descendants("w"):这个方法会获取当前<p>节点下所有层级的<w>节点,确保不会遗漏任何分词内容。如果你用Element("w")只会取第一个直接子节点,这就是常见的遗漏问题根源。- 时间格式转换:SRT格式要求毫秒用逗号分隔,而很多XML字幕用点,所以用
Replace('.', ',')做转换。 - 拼接文本:用
string.Join(" ", ...)把每个<w>的文本拼接成完整的字幕行,同时用Trim()去掉每个分词的多余空格。
处理带命名空间的XML
如果你的XML带有命名空间(比如TTML格式的<tt xmlns="http://www.w3.org/2006/ttaf1">),只需要添加命名空间的处理即可:
// 定义XML命名空间 XNamespace ns = "http://www.w3.org/2006/ttaf1"; var srtEntries = xmlSubtitles.Descendants(ns + "p") .Select((paragraph, index) => new { SequenceNumber = index + 1, StartTime = paragraph.Attribute("begin").Value.Replace('.', ','), EndTime = paragraph.Descendants(ns + "w").Last().Attribute("end").Value.Replace('.', ','), SubtitleText = string.Join(" ", paragraph.Descendants(ns + "w").Select(w => w.Value.Trim())) });
这样就能正确解析带命名空间的XML字幕了。
内容的提问来源于stack exchange,提问作者user4856537
相关产品推荐
相关产品推荐

