C#如何给XDocument添加DTD声明

发布时间 - 2026-01-08 00:00:00    点击率:
XDocument 默认不支持添加 DTD,因其基于轻量级 LINQ to XML,为安全与简化模型而忽略 DTD 解析和序列化;需用 XmlWriter 配合 DoctypePublic/DoctypeSystem 输出简单 DOCTYPE,复杂内联 DTD 则须改用 XmlDocument。

C# 中的 XDocument 默认不支持直接添加 DTD(Document Type Definition)声明,因为 XDocument 基于 LINQ to XML,其设计目标是轻量、符合 W3C XML 1.0 核心规范,而DTD 属于已逐步被弃用的旧式 XML 特性,且 LINQ to XML 明确不提供对 DTD 的解析或序列化支持

为什么 XDocument 不允许添加 DTD

Microsoft 官方文档明确指出:XDocument 在加载或保存时会忽略 DTD;调用 Save()ToString() 时,DTD 不会被输出。这是出于安全(如防止 XXE 攻击)和简化模型的考虑。

  • DTD 可能引入外部实体、参数实体等复杂特性,与 LINQ to XML 的不可变、纯内存 DOM 模型冲突
  • XDocumentDeclaration 属性仅支持 XDeclaration(即 XML 声明,如 ),不包含 DTD
  • 尝试在节点中手动插入 ..> 字符串会导致解析失败或被自动过滤

绕过限制:用 XmlWriter 手动写入 DTD

若必须生成带 DTD 的 XML 字符串(例如对接遗留系统),可借助 XmlWriter 配合自定义设置,在写入根元素前显式写出 DTD 行:

var doc = new XDocument(
    new XElement("root",
        new XElement("child", "content")
    )
);

using (var stringWriter = new StringWriter()) using (var writer = XmlWriter.Create(stringWriter, new XmlWriterSettings { OmitXmlDeclaration = false, Indent = true, DoctypeSystem = "my.dtd", // 可选:SYSTEM 公共 ID DoctypePublic = "-//MyOrg//DTD MyDoc 1.0//EN" // 可选:PUBLIC ID })) { // 手动写入 DOCTYPE(XmlWriter 会在 WriteStartDocument 后自动加) writer.WriteStartDocument(); // 注意:DoctypePublic/DoctypeSystem 设置会触发 XmlWriter 自动写入 DOCTYPE 行 doc.Root?.WriteTo(writer); writer.Flush();

string xmlWithDtd = stringWriter.ToString();
// 输出示例:
// 
// 
// content

}

⚠️ 注意:此方式依赖 XmlWriterDoctypePublic / DoctypeSystem 设置,仅适用于简单 PUBLIC/SYSTEM 引用;无法写入内联 DTD(如包含 ENTITY 或 ATTLIST 定义),因为 XmlWriter 不支持嵌入式 DTD 内容。

需要完整内联 DTD?改用 XmlDocument

如果业务强依赖内联 DTD(例如定义实体 或元素约束),应切换到传统 XmlDocument

  • XmlDocument 支持 CreateDocumentType() 方法创建 XmlDocumentType 节点
  • 可通过 AppendChild(docType) 将 DTD 插入文档开头
  • 支持完整 DTD 语法(包括内部子集、外部子集、参数实体等)

示例:

var doc = new XmlDocument();
var docType = doc.CreateDocumentType("root", "-//MyOrg//DTD MyDoc 1.0//EN", "my.dtd", null);
doc.AppendChild(docType);

var root = doc.CreateElement("root"); root.AppendChild(doc.CreateElement("child")).InnerText = "content"; doc.AppendChild(root);

string xml = doc.OuterXml; // 包含完整 DOCTYPE

总结与建议

对于绝大多数现代场景,避免使用 DTD —— 改用 XML Schema(XSD)或 JSON Schema 更安全、更易维护。若仅需兼容性输出简单 DOCTYPE 声明:

  • 优先用 XmlWriter + DoctypePublic/DoctypeSystem(轻量、可控)
  • 禁用 XDocument.Save() 直接输出,它不会保留 DTD
  • 涉及复杂 DTD 逻辑时,退回 XmlDocument 是唯一可靠选择
  • 生产环境注意关闭 DTD 解析(XmlReaderSettings.DtdProcessing = DtdProcessing.Prohibit),防范 XXE


# js  # json  # app  # microsoft  # c#  # 为什么  # xml  # 字符串  # public  # dom  # linq  # 不支持  # 可选  # 这是  # 文档  # 序列化  # 适用于  # 会在  # 自定义  # 可通过  # 因其 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 奇安信“盘古石”团队突破 iOS 26.1 提权  Linux系统命令中screen命令详解  非常酷的网站设计制作软件,酷培ai教育官方网站?  实例解析Array和String方法  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  C语言设计一个闪闪的圣诞树  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  如何将凡科建站内容保存为本地文件?  Android中AutoCompleteTextView自动提示  Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制  如何安全更换建站之星模板并保留数据?  WEB开发之注册页面验证码倒计时代码的实现  制作企业网站建设方案,怎样建设一个公司网站?  ,交易猫的商品怎么发布到网站上去?  如何实现javascript表单验证_正则表达式有哪些实用技巧  Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)  Laravel怎么连接多个数据库_Laravel多数据库连接配置  Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境  Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程  Win11怎么修改DNS服务器 Win11设置DNS加速网络【指南】  php json中文编码为null的解决办法  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程  Laravel如何优化应用性能?(缓存和优化命令)  如何在腾讯云服务器上快速搭建个人网站?  Python结构化数据采集_字段抽取解析【教程】  手机怎么制作网站教程步骤,手机怎么做自己的网页链接?  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?  如何解决hover在ie6中的兼容性问题  大连网站制作公司哪家好一点,大连买房网站哪个好?  Python并发异常传播_错误处理解析【教程】  Android okhttputils现在进度显示实例代码  长沙企业网站制作哪家好,长沙水业集团官方网站?  Laravel如何使用Service Provider服务提供者_Laravel依赖注入与容器绑定【深度】  Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】  如何用AWS免费套餐快速搭建高效网站?  香港服务器网站生成指南:免费资源整合与高速稳定配置方案  如何在服务器上配置二级域名建站?  Laravel如何创建和注册中间件_Laravel中间件编写与应用流程  Laravel如何处理CORS跨域请求?(配置示例)  香港服务器网站推广:SEO优化与外贸独立站搭建策略  JavaScript如何实现继承_有哪些常用方法  网站建设整体流程解析,建站其实很容易!  网页设计与网站制作内容,怎样注册网站?  如何在Windows服务器上快速搭建网站?  如何快速辨别茅台真假?关键步骤解析  Java垃圾回收器的方法和原理总结  如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】