Расширение модели DOM
Платформа Microsoft .NET Framework включает базовый набор классов, обеспечивающих реализацию модели DOM. Объект XmlNode и его производные классы предоставляют методы и свойства, позволяющие переходить по содержимому и структуре XML-документа, запрашивать и изменять это содержимое и структуру.
Если содержимое XML загружается в память с помощью модели DOM, созданные узлы содержат такие сведения, как имя узла, тип узла и так далее. Могут быть случаи, когда необходимы конкретные данные об узле, которые не предоставляют базовые классы. Например, может потребоваться узнать номер строки и позицию узла. В этом случае можно произвести новые классы из существующих классов 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.