我目前正在编写一个用于修改和处理特定XML文档的应用程序。
我的应用程序具有用于撤消/重做更改的堆栈,并且还将XML DOM上的更改记录到调试控制台。对于DOM的每次更改,应用程序都会对文档进行验证,因此用户可以直接获得无效条目的反馈。
我的问题是XmlDocument.Validate()方法触发XmlDocument.NodeInserted Action。这导致无休止的回调循环。 我该如何防止这种行为?
我的代码的一部分:
初始化/加载文档:
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;
...
}
答案 0 :(得分:0)
The documentation for Validate()说:
Validate方法执行信息集扩充。具体来说,之后 成功验证,应用架构默认值,文本值 根据需要转换为原子值,类型信息为 与经过验证的信息项相关联。结果是 XmlDocument中以前未键入的XML子树被替换为 键入子树。
在我看来,您需要添加一些其他状态来跟踪更改是“有意的”还是验证过程中发生的“信息集增强”的结果。像跟踪“ IsValidating”状态并避免在_document.Validate()调用时一样。