Estensione del DOM

.NET Framework comprende un gruppo di classi di base tramite cui viene implementato il Document Object Model (DOM). Tramite XmlNode e le classi derivate sono forniti metodi e proprietà che consentono di esplorare, eseguire query e modificare il contenuto e la struttura di un documento XML.

Quando il contenuto dell'XML è caricato in memoria tramite il DOM, nei nodi creati sono contenute informazioni come il nome del nodo, il tipo di nodo e così via. Potrebbero presentarsi casi in cui sono necessarie informazioni specifiche sul nodo non fornite dalle classi di base. È possibile ad esempio che si voglia conoscere il numero di riga e la posizione del nodo. In questo caso, è possibile derivare nuove classi dalle classi esistenti del DOM e aggiungere ulteriori funzionalità.

La derivazione di nuove classi è soggetta a due direttive generali:

  • Si consiglia di non eseguire mai la derivazione dalla classe XmlNode. Si consiglia invece di eseguire la derivazione delle classi dalla classe corrispondente al tipo di nodo a cui si è interessati. Se, ad esempio, si desidera restituire ulteriori informazioni sui nodi degli attributi, è possibile eseguire la derivazione dalla classe XmlAttribute.
  • Ad eccezione dei metodi per la creazione dei nodi, si consiglia durante l'override di una funzione, di chiamare sempre la versione di base della funzione e di aggiungervi un'eventuale elaborazione aggiuntiva.

Creazione di istanze dei nodi

Nella classe XmlDocument sono contenuti i metodi per la creazione di nodi. Quando viene caricato un file XML, questi metodi vengono chiamati per creare i nodi. È possibile eseguire l'override di questi metodi in modo che le istanze dei nodi vengano create quando viene caricato un documento. Se, ad esempio, è stata estesa la classe XmlElement, viene ereditata la classe XmlDocument e viene eseguito l'override del metodo CreateElement.

Nell'esempio seguente viene illustrato come eseguire l'override del metodo CreateElement per restituire l'implementazione della classe 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
[C#]
class LineInfoDocument : XmlDocument {
  public override XmlElement CreateElement(string prefix, string localname, string nsURI) {
  LineInfoElement elem = new LineInfoElement(prefix, localname, nsURI, this);
  return elem;
  }

Estensione di una classe

Per estendere una classe, eseguire la derivazione della classe da una delle classi esistenti del DOM. È possibile quindi eseguire l'override dei metodi o delle proprietà virtuali nella classe di base oppure aggiungere quelli di propria creazione.

Nell'esempio seguente viene creata una nuova classe, che implementa la classe XmlElement e l'interfaccia IXmlLineInfo. Metodi e proprietà aggiuntivi sono definiti per consentire all'utente di raccogliere informazioni sulla riga.

Class LineInfoElement
   Inherits XmlElement
   Implements IXmlLineInfo 'ToDo: Add Implements Clauses for implementation methods of these interface(s)
   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 'New
   
   Public Sub SetLineInfo(linenum As Integer, linepos As Integer)
      lineNumber = linenum
      linePosition = linepos
   End Sub 'SetLineInfo
   
   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 'HasLineInfo
End Class 'LineInfoElement ' End LineInfoElement class.
[C#]
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.

Esempio

Nell'esempio seguente viene contato il numero di elementi in un documento XML.

Imports System
Imports System.Xml
Imports System.IO

 _

Class LineInfoDocument
   Inherits XmlDocument
   
   Private elementCount As Integer
   
   Friend Sub New()
      elementCount = 0
   End Sub 'New
   
   
   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
   
   
   Public Sub IncrementElementCount()
      elementCount += 1
   End Sub 'IncrementElementCount
   
   
   Public Function GetCount() As Integer
      Return elementCount
   End Function 'GetCount
End Class 'LineInfoDocument
 _ '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 'Main 
End Class 'Test
[C#]
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());

  }
} 

Input

books.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>

Output

Number of elements in book.xml: 3

Un esempio in cui viene illustrato come estendere le classi del DOM XML (System.Xml) è riportato in www.gotdotnet.com/userfiles/XMLDom/extendDOM.zip.

Per ulteriori esempi, vedere Creazione di un writer XML personalizzato.

Gestore degli eventi dei nodi

Nell'implementazione del DOM da parte di .NET Framework è compreso anche un sistema di eventi che consente di ricevere e gestire gli eventi, quando cambiano i nodi di un documento XML. Utilizzando le classi XmlNodeChangedEventHandler e XmlNodeChangedEventArgs è possibile catturare gli eventi NodeChanged, NodeChanging, NodeInserted, NodeInserting, NodeRemoved e NodeRemoving.

Il processo di gestione degli eventi funziona esattamente allo stesso modo nelle classi derivate e nelle classi originali del DOM.

Per ulteriori informazioni relative alla gestione degli eventi dei nodi, vedere Eventi e delegati e Delegato XmlNodeChangedEventHandler.

Attributi predefiniti e metodo CreateElement

Se si esegue l'override del metodo CreateElement in una classe derivata, gli attributi predefiniti non vengono aggiunti alla creazione di nuovi elementi durante la modifica del documento. Questo problema si verifica solo durante la modifica. Poiché il metodo CreateElement è responsabile dell'aggiunta di attributi predefiniti a un XmlDocument, è necessario codificare questa funzionalità nel metodo CreateElement. Se si carica un XmlDocument in cui sono compresi attributi predefiniti, questi verranno gestiti correttamente. Per ulteriori informazioni sugli attributi predefiniti, vedere Creazione di nuovi attributi per gli elementi nel DOM.

Vedere anche

Modello a oggetti di documenti XML (Document Object Model, DOM)