Microsoft .NET Framework 包括一组基类,这些类提供 XML 文档对象模型(DOM)的实现。 该 XmlNode类及其派生类提供方法和属性,可用于导航、查询和修改 XML 文档的内容和结构。
使用 DOM 将 XML 内容加载到内存中时,创建的节点包含节点名称、节点类型等信息。 在某些情况下,可能需要基类不提供的特定节点信息。 例如,可能需要查看节点的行号和位置。 在这种情况下,可以从现有 DOM 类派生新类并添加其他功能。
派生新类时有两个常规准则:
建议永远不要从 XmlNode 类派生。 相反,建议从与对您有用的节点类型对应的类派生类。 例如,如果要返回有关属性节点的其他信息,可以从类派生 XmlAttribute 。
除了节点创建方法之外,建议在重写函数时,应始终调用函数的基本版本,然后添加任何其他处理。
创建自己的节点实例
该 XmlDocument 类包含节点创建方法。 加载 XML 文件时,将调用这些方法来创建节点。 可以重写这些方法,以便在加载文档时创建节点实例。 例如,如果扩展了 XmlElement 类,则需要继承 XmlDocument 类并重写 CreateElement 方法。
以下示例演示如何重写 CreateElement 方法以返回您对 XmlElement 类的具体实现。
Class LineInfoDocument
Inherits XmlDocument
Public Overrides Function CreateElement(prefix As String, localname As String, nsURI As String) As XmlElement
Dim elem As New LineInfoElement(prefix, localname, nsURI, Me)
Return elem
End Function 'CreateElement
End Class 'LineInfoDocument
class LineInfoDocument : XmlDocument
{
public override XmlElement CreateElement(string prefix, string localname, string nsURI)
{
LineInfoElement elem = new LineInfoElement(prefix, localname, nsURI, this);
return elem;
}
}
扩展类
若要扩展类,请从现有 DOM 类之一派生类。 然后,可以重写基类中的任何虚拟方法或属性或添加您自己的虚拟方法或属性。
在以下示例中,将创建一个新类,该类实现 XmlElement 该类和 IXmlLineInfo 接口。 定义了其他方法和属性,允许用户收集行信息。
Class LineInfoElement
Inherits XmlElement
Implements IXmlLineInfo
Private lineNumber As Integer = 0
Private linePosition As Integer = 0
Friend Sub New(prefix As String, localname As String, nsURI As String, doc As XmlDocument)
MyBase.New(prefix, localname, nsURI, doc)
CType(doc, LineInfoDocument).IncrementElementCount()
End Sub
Public Sub SetLineInfo(linenum As Integer, linepos As Integer)
lineNumber = linenum
linePosition = linepos
End Sub
Public ReadOnly Property LineNumber() As Integer
Get
Return lineNumber
End Get
End Property
Public ReadOnly Property LinePosition() As Integer
Get
Return linePosition
End Get
End Property
Public Function HasLineInfo() As Boolean
Return True
End Function
End Class ' End LineInfoElement class.
class LineInfoElement : XmlElement, IXmlLineInfo {
int lineNumber = 0;
int linePosition = 0;
internal LineInfoElement( string prefix, string localname, string nsURI, XmlDocument doc ) : base( prefix, localname, nsURI, doc ) {
( (LineInfoDocument)doc ).IncrementElementCount();
}
public void SetLineInfo( int linenum, int linepos ) {
lineNumber = linenum;
linePosition = linepos;
}
public int LineNumber {
get {
return lineNumber;
}
}
public int LinePosition {
get {
return linePosition;
}
}
public bool HasLineInfo() {
return true;
}
} // End LineInfoElement class.
示例:
以下示例对 XML 文档中的元素数进行计数:
Imports System.Xml
Imports System.IO
Class LineInfoDocument
Inherits XmlDocument
Private elementCount As Integer
Friend Sub New()
elementCount = 0
End Sub
Public Overrides Function CreateElement(prefix As String, localname As String, nsURI As String) As XmlElement
Dim elem As New LineInfoElement(prefix, localname, nsURI, Me)
Return elem
End Function
Public Sub IncrementElementCount()
elementCount += 1
End Sub
Public Function GetCount() As Integer
Return elementCount
End Function
End Class 'End LineInfoDocument class.
Class LineInfoElement
Inherits XmlElement
Friend Sub New(prefix As String, localname As String, nsURI As String, doc As XmlDocument)
MyBase.New(prefix, localname, nsURI, doc)
CType(doc, LineInfoDocument).IncrementElementCount()
End Sub 'New
End Class 'LineInfoElement
_ 'End LineInfoElement class.
Public Class Test
Private filename As [String] = "book.xml"
Public Shared Sub Main()
Dim doc As New LineInfoDocument()
doc.Load(filename)
Console.WriteLine("Number of elements in {0}: {1}", filename, doc.GetCount())
End Sub
End Class
using System;
using System.Xml;
using System.IO;
class LineInfoDocument : XmlDocument {
int elementCount;
internal LineInfoDocument():base() {
elementCount = 0;
}
public override XmlElement CreateElement( string prefix, string localname, string nsURI) {
LineInfoElement elem = new LineInfoElement(prefix, localname, nsURI, this );
return elem;
}
public void IncrementElementCount() {
elementCount++;
}
public int GetCount() {
return elementCount;
}
} // End LineInfoDocument class.
class LineInfoElement:XmlElement {
internal LineInfoElement( string prefix, string localname, string nsURI, XmlDocument doc ):base( prefix,localname,nsURI, doc ){
((LineInfoDocument)doc).IncrementElementCount();
}
} // End LineInfoElement class.
public class Test {
const String filename = "book.xml";
public static void Main() {
LineInfoDocument doc =new LineInfoDocument();
doc.Load(filename);
Console.WriteLine("Number of elements in {0}: {1}", filename, doc.GetCount());
}
}
输入
book.xml
<!--sample XML fragment-->
<book genre='novel' ISBN='1-861001-57-5' misc='sale-item'>
<title>The Handmaid's Tale</title>
<price>14.95</price>
</book>
输出
Number of elements in book.xml: 3
节点事件处理程序
DOM 的 .NET Framework 实现还包括一个事件系统,使你可以在 XML 文档中的节点发生更改时接收和处理事件。 使用XmlNodeChangedEventHandler 和 XmlNodeChangedEventArgs 类,您可以捕获 NodeChanged
、NodeChanging
、NodeInserted
、NodeInserting
、NodeRemoved
和 NodeRemoving
事件。
事件处理过程在派生类中的工作方式与原始 DOM 类中完全相同。
有关节点事件处理的详细信息,请参阅 事件 和 XmlNodeChangedEventHandler。
默认属性和 CreateElement 方法
如果在派生类中重写 CreateElement 该方法,则在编辑文档时创建新元素时,不会添加默认属性。 这只是编辑时出现的问题。 CreateElement方法负责向XmlDocument添加默认属性,因此必须在CreateElement方法中对此功能进行编码。 如果您正在加载一个 XmlDocument 并且它包含默认属性,则这些属性将得到正确处理。 有关默认属性的详细信息,请参阅 DOM 中的“为元素创建新属性”。