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

使用System.Xml.XmlReader读取含非法XML处理指令数据的问题问询

问题根因

你遇到的报错是因为服务端返回的开头<? LLSD/XML ?>不符合XML处理指令(PI)的语法规范:XML要求处理指令开头<?之后必须紧跟PI名称,不能有空格。即便你在XmlReaderSettings里开启了IgnoreProcessingInstructions = true,XmlReader也会先校验PI的语法结构再执行忽略逻辑,语法校验不通过会直接抛出异常,该配置不会生效。
另外你现有的代码还存在一个明显问题:定义了XmlReaderSettings但没有传入XmlReader.Create方法,所有你配置的校验规则实际都没有生效。

解决方案1:预处理跳过非法开头行(推荐)

因为你的非法处理指令是单独占第一行,其余内容都是规范XML,最简单的方式是先读取并丢弃第一行,再用剩下的流创建XmlReader即可,代码示例如下:

public static OSD DeserializeLLSDXml(Stream xmlStream)
{
    XmlReaderSettings settings = new XmlReaderSettings
    {
        ValidationType = ValidationType.None,
        CheckCharacters = false,
        IgnoreComments = true,
        IgnoreProcessingInstructions = true,
        DtdProcessing = DtdProcessing.Prohibit
    };
    // 注意匹配你实际的编码,默认按UTF-8处理,有需要可自行调整
    StreamReader sr = new StreamReader(xmlStream, Encoding.UTF8);
    string firstLine = sr.ReadLine();
    // 判断第一行是否为非法处理指令,不是的话需要把已读取的第一行加回内容
    if (!firstLine.TrimStart().StartsWith("<? LLSD/XML"))
    {
        var remainingContent = firstLine + Environment.NewLine + sr.ReadToEnd();
        var remainingStream = new MemoryStream(Encoding.UTF8.GetBytes(remainingContent));
        remainingStream.Position = 0;
        sr = new StreamReader(remainingStream);
    }
    // 注意此处要传入settings,配置才会生效
    using (XmlReader xrd = XmlReader.Create(sr, settings))
    {
        return DeserializeLLSDXml(xrd);
    }
}

解决方案2:全局过滤非法处理指令(适配PI不独占一行的场景)

如果你的非法处理指令可能和其他XML内容在同一行,可以用字符串替换的方式先把所有<? LLSD/XML ?>片段移除再解析:

public static OSD DeserializeLLSDXml(Stream xmlStream)
{
    XmlReaderSettings settings = new XmlReaderSettings
    {
        ValidationType = ValidationType.None,
        CheckCharacters = false,
        IgnoreComments = true,
        IgnoreProcessingInstructions = true,
        DtdProcessing = DtdProcessing.Prohibit
    };
    string xmlContent = new StreamReader(xmlStream, Encoding.UTF8).ReadToEnd();
    // 替换所有非法处理指令片段
    xmlContent = xmlContent.Replace("<? LLSD/XML ?>", string.Empty);
    var processedStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlContent));
    processedStream.Position = 0;
    using (XmlReader xrd = XmlReader.Create(processedStream, settings))
    {
        return DeserializeLLSDXml(xrd);
    }
}

注意事项

  • 两种方案都需要注意匹配你实际的XML编码,如果服务端返回的不是UTF-8,需要调整Encoding参数
  • 方案1的性能更优,不需要把整个XML内容读入内存,适合大XML场景

内容的提问来源于stack exchange,提问作者Cinder Biscuits

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:54:01