c# - XmlDocument.NodeInserted 在 XmlDocument.Validate() 上触发
问题描述
我目前正在编写一个应用程序来修改和处理特定的 XML 文档。
我的应用程序有一个用于撤消/重做更改的堆栈,还将 XML DOM 上的更改记录到调试控制台。在每次 DOM 更改时,应用程序都会验证文档,因此用户可以直接获得有关无效条目的反馈。
我的问题是,XmlDocument.Validate() 方法触发了 XmlDocument.NodeInserted 操作。这会导致无休止的回调循环。我怎样才能防止这种行为?
我的部分代码:
初始化/加载文档:
private void ParseStyleSheet(FileInfo stylesFile)
{
// load document
XmlDocument document = new XmlDocument();
document.PreserveWhitespace = true;
document.Schemas = StyleSchemaSet.GetSchemaset();
document.Load(stylesFile.FullName);
// add event handlers
document.NodeChanged += XmlNodeChangedAction;
document.NodeChanged += _undoMngr.XmlNodeChangedEventHandler;
document.NodeInserted += XmlNodeChangedAction;
document.NodeInserted += _undoMngr.XmlNodeChangedEventHandler;
document.NodeRemoved += XmlNodeChangedAction;
document.NodeRemoved += _undoMngr.XmlNodeChangedEventHandler;
// set namespace
XmlNamespaceManager nameSpaceMngr = new
XmlNamespaceManager(document.NameTable);
...
}
更改处理程序/验证回调:
private void XmlNodeChangedAction(object src, XmlNodeChangedEventArgs args)
{
// debug outputs
Debug.WriteLine("XML node is changing");
Debug.Indent();
Debug.WriteLine(args.Action);
Debug.WriteLine("Old: " + args.OldValue);
Debug.WriteLine("New: " + args.NewValue);
_document.Validate(this.ValidationEventCallBack);//TODO leads to loop
// undindent debug
Debug.Unindent();
}
private void ValidationEventCallBack(object sender, ValidationEventArgs args)
{
switch (args.Severity)
{
case XmlSeverityType.Error:
//TODO maybe throw for GUI message?
Debug.WriteLine("XSD Error: " + args.Message);
break;
case XmlSeverityType.Warning:
Debug.WriteLine("XSD Warning: " + args.Message);
break;
default:
break;
}
}
一旦我更改了一个节点,我就会得到一个无限循环的更改,这也显示在调试器控制台中:
XML node is changing
Change
Old: 20px
New: 25px
XML node is changing
Insert
Old: #ebebeb
New: #ebebeb
XML node is changing
Insert
Old: #ebebeb
New: #ebebeb
XML node is changing
Insert
Old: #ebebeb
New: #ebebeb
XML node is changing
Insert
...
更新(感谢 Tao 的提示):
如果在加载后和添加 NodeInserted 委托之前直接验证了文档,则不再发生循环。像这样,由于第一次验证,所有 DOM 更改都已经发生。
private void ParseStyleSheet(FileInfo stylesFile)
{
// load document
XmlDocument document = new XmlDocument();
document.PreserveWhitespace = true;
document.Schemas = StyleSchemaSet.GetSchemaset();
document.Load(stylesFile.FullName);
document.Validate(ValidationEventCallBack);
// add event handlers
document.NodeChanged += XmlNodeChangedAction;
document.NodeChanged += _undoMngr.XmlNodeChangedEventHandler;
document.NodeInserted += XmlNodeChangedAction;
document.NodeInserted += _undoMngr.XmlNodeChangedEventHandler;
document.NodeRemoved += XmlNodeChangedAction;
document.NodeRemoved += _undoMngr.XmlNodeChangedEventHandler;
...
}
解决方案
Validate 方法执行信息集扩充。具体来说,在成功验证后,应用架构默认值,必要时将文本值转换为原子值,并将类型信息与经过验证的信息项相关联。结果是 XmlDocument 中先前未键入的 XML 子树被键入的子树替换。
在我看来,您需要添加一些额外的状态来跟踪更改是“有意的”,还是验证期间发生的“信息集扩充”的结果。类似于跟踪“IsValidating”状态并在该状态下避免 _document.Validate() 调用。
推荐阅读
- android - 从 Android 发送大文件时 io.socket 重启
- node.js - Socket.io 中的 require 函数如何在 Node.js 中获取参数
- sql - 将“HH:MM AM/PM”varchar 列转换为 Teradata 中的时间
- python - 我没有得到正确的公斤值
- excel - 如何根据在另一个字段的一部分中找到的文本字符串向某些字段添加文本字符串
- javascript - Jest 中的模拟模块
- python - 在 Python 中绘制多个日期和值对列
- sql-server - 查询将数据从一个数据库传输到另一个数据库
- javascript - 文档未定义
- excel - Excel 冻结窗格在使用自定义视图和清除过滤器时起作用