You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:使用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

常见问题原因

你之前没获取到所有节点,大概率是因为LINQ查询里只取了单个(比如用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:45:08