Creazione di un writer XML personalizzato

L'implementazione di XmlTextWriter non esegue le operazioni elencate di seguito.

  • XmlTextWriter non consente di verificare che i nomi degli elementi o degli attributi sono validi.
  • XmlTextWriter consente di scrivere i caratteri Unicode nell'intervallo compreso tra 0x0 e 0x20, e i caratteri 0xFFFE e 0xFFFF, che non sono caratteri XML.
  • XmlTextWriter non rileva gli attributi duplicati. Gli attributi duplicati vengono scritti senza generare un'eccezione.

Se questi tre elementi sono critici per le proprie esigenze, è possibile scrivere un writer personalizzato che estenda l'XmlTextWriter corrente, aggiungendo queste funzionalità.

Nell'esempio riportato di seguito viene illustrato come modificare il writer XML, sovrascrivendo i metodi WriteString e WriteStartElement. L'esempio di codice non garantisce la scrittura di un XML valido, verifica solo che le stringhe riportate non abbiano caratteri al di fuori dei limiti e che i nomi degli elementi siano validi. I nomi degli attributi non vengono verificati.

  1. Il primo passo consiste nel definire un metodo che verifichi che i caratteri in una stringa siano caratteri validi, secondo la specifica W3C. Questo metodo viene utilizzato per verificare che le stringhe riportate dal writer siano corrette. Di seguito sono riportati i test specifici eseguiti sulle stringhe di caratteri:

    • Verifica che nessun carattere abbia un valore esadecimale superiore a 0xFFFD o inferiore a 0x20.
    • Verifica che il carattere non sia uguale al carattere di tabulazione (\t), di nuova riga (\n), di ritorno a capo (\r), e non sia un carattere XML non valido al di sotto dell'intervallo di 0x20. Se si verifica uno di questi caratteri, viene generata un'eccezione.

    Il metodo è illustrato nel codice di esempio riportato di seguito.

    internal void CheckUnicodeString(String value) 
        {
        for (int i=0; i < value.Length; ++i) {
            if (value[i] > 0xFFFD) 
            {
                throw new Exception("Invalid Unicode");
            } 
            else if (value[i] < 0x20 && value[i] != '\t' & value[i] != '\n' & value[i] != '\r')
            {
                throw new Exception("Invalid Xml Characters");
            }
        }
    
  2. La fase successiva consiste nell'utilizzare il metodo definito al punto 1 per sovrascrivere il metodo WriteString in XmlTextWriter. Il metodo WriteString sovrascritto genera un'eccezione se i caratteri nella stringa sono al di fuori dei limiti dell'intervallo di caratteri accettabile.

            public override void WriteString(String value) 
             {
                CheckUnicodeString(value);
                base.WriteString(value);
             }
    

Per verificare che i nomi scritti dal metodo WriteStartElement siano validi, viene utilizzato il metodo EncodeLocalName della classe XmlConvert. Il metodo EncodeLocalName assicura che i caratteri nel nome siano validi, convertendo tutti i carattere non validi in una rappresentazione valida. Ad esempio, Order Details viene convertito in Order_x0020_Details. Per ulteriori informazioni su EncodeLocalName, vedere Metodo XmlConvert.EncodeLocalName.

public override void WriteStartElement(string prefix, string localName, string ns) 
{
   base.WriteStartElement(prefix,
        XmlConvert.EncodeLocalName(localName),ns);
}

Invece di utilizzare il metodo EncodeLocalName, il metodo VerifyName della classe XmlConvert verifica inoltre che il nome di un elemento o di un attributo sia valido. Il metodo VerifyName restituisce il nome come argomento di restituzione se il nome è valido o genera un'eccezione se il nome non è valido. Questo risulta particolarmente quando è necessario sapere che un errore si è verificato a causa di un nome non valido. Nell'esempio seguente viene illustrato come creare il metodo WriteStartElement utilizzando il metodo VerifyName per verificare la validità del nome.

public override void WriteStartElement(string prefix, string localName, 
                                       string ns) 
{
   base.WriteStartElement(prefix,
        XmlConvert.VerifyName(localName),ns);
}

Nota   Non è necessario sovrascrivere nessuno degli altri metodi WriteStartElement poiché tutti richiamano il metodo sopra descritto.

Esempio di codice completo di writer conforme

L'esempio di codice riportato di seguito è un elenco completo della definizione della classe. Per garantire che vengano sempre scritti caratteri validi, è necessario eseguire l'override di altri metodi, come WriteDocType, WriteAttributeString, WriteElementString, e WriteCharEntity. L'esecuzione dell'override di questi metodi è simile a quella del metodo WriteStartElement, come mostrato nell'esempio di codice che segue.

Imports System
Imports System.IO
Imports System.Text
Imports System.Xml
Imports System.Collections
Imports Microsoft.VisualBasic

'------------------------------------------------------------------
' Class derived from XmlTextWriter classs.
'
' This example only overrides the WriteString and WriteStartElement
' methods.
'------------------------------------------------------------------
namespace MyWriter.ConformWriter 

    public class ConformWriter : Inherits XmlTextWriter

        private sub CheckUnicodeString(ByVal value as String) 
            Dim i as Integer
            Dim iVal as Integer
            for i=0 to value.Length-1
                iVal = Convert.ToInt16(value.Chars(i))
                if (iVal > &HFFFD) 
                    throw new Exception("Invalid Unicode")
                else 
                    if iVal < &H20 And (iVal <> 9 And iVal <> 13 And iVal <> 10) Then
                        throw new Exception("Invalid Xml Characters")
                    end if
                end if
            next
        end sub

        public sub New(ByVal fileName as String, ByVal encoding as Encoding)
            MyBase.New(fileName, encoding) 
        end sub

        Overrides public sub WriteString(ByVal value as String) 
            CheckUnicodeString(value)
            MyBase.WriteString(value)
        end sub

        Overrides Overloads public sub WriteStartElement(ByVal prefix As String, ByVal localname As String, ByVal ns As String) 
            MyBase.WriteStartElement(prefix, XmlConvert.EncodeLocalName(localName), ns)
        end sub
        
    end class
end namespace
[C#]
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Collections;

//------------------------------------------------------------------
// Class derived from XmlTextWriter classs.
//
// This sample only overrides the WriteString and WriteStartElement
// methods.
//------------------------------------------------------------------
namespace MyWriter.ConformWriter {

    public class ConformWriter : XmlTextWriter
    {
       internal void CheckUnicodeString(String value) {
           for (int i=0; i < value.Length; ++i) {
                if (value[i] > 0xFFFD) {
                    throw new Exception("Invalid Unicode");
                        } else if (value[i] < 0x20 && value[i] != '\t' & value[i] != '\n' & value[i] != '\r') {
                    throw new Exception("Invalid Xml Characters");
                }
            }
        }

        public ConformWriter(String fileName, Encoding encoding):base(fileName, encoding) {}

        public override void WriteString(String value) {
            CheckUnicodeString(value);
            base.WriteString(value);
        }

        public override void WriteStartElement(string prefix, string localName, string ns) {
            base.WriteStartElement(prefix, XmlConvert.EncodeLocalName(localName), ns);
        }
    }
}

Vedere anche

Scrittura dell'XML con XmlWriter