Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

NIB: conversione di caratteri speciali durante la scrittura del contenuto XML

In XmlWriter è incluso un metodo, WriteRaw, che consente di creare manualmente un markup non elaborato. Questo metodo impedisce che venga eseguito l'escape dei caratteri speciali, a differenza del metodo WriteString che esegue l'escape di alcune stringhe nel riferimento all'entità equivalente. I caratteri di escape sono elencati nella sezione 2.4 Character Data and Markup della raccomandazione XML 1.0 e nella sezione 3.3.3 Attribute-Value Normalization della raccomandazione Extensible Markup Language (XML) 1.0 (fourth edition). Se viene chiamato il metodo WriteString quando si scrive il valore di un attributo, viene eseguito l'escape in ' e ". I valori di caratteri compresi nell'intervallo 0x-0x1F sono codificati come entità di caratteri numerici da � a , esclusi gli spazi vuoti 0x9, 0x10 e 0x13.

Pertanto, il principio guida che determina quando utilizzare WriteString o WritingRaw è basato sul fatto che WriteString viene utilizzato quando è necessario esaminare ogni carattere ricercando i caratteri delle entità, mentre WriteRaw scrive esattamente ciò che gli viene fornito.

Il metodo WriteNode copia tutti gli elementi del nodo corrente e il lettore viene posizionato nel writer. Il lettore viene quindi passato al nodo di pari livello successivo per un'ulteriore elaborazione. Il metodo WriteNode consente di estrarre rapidamente informazioni da un documento e di inserirle in un altro.

Nella seguente tabella sono illustrati i tipi di nodo supportati per il metodo WriteNode.

Tipo di nodo

Descrizione

Element

Scrive il nodo dell'elemento e tutti i nodi Attribute.

Attribute

Nessuna operazione. Utilizza WriteStartAttribute o WriteAttributeString per scrivere l'attributo.

Text

Scrive il nodo di tipo text.

CDATA

Scrive il nodo della sezione CDATA.

EntityReference

Scrive il nodo EntityReference.

ProcessingInstruction

Scrive il nodo PI (Processing Instruction).

Comment

Scrive il nodo Comment.

DocumentType

Scrive il nodo DocType.

Whitespace

Scrive il nodo Whitespace.

SignificantWhitespace

Scrive il nodo Whitespace.

EndElement

Nessuna operazione.

EndEntity

Nessuna operazione.

Nell'esempio seguente viene illustrata la differenza tra i metodi WriteString e WriteRaw quando viene fornito il carattere"<". In questo esempio di codice viene utilizzato il metodo WriteString.

w.WriteStartElement("myRoot");
w.WriteString("<");
w.WriteEndElement();
XmlTextWriter tw = new XmlTextWriter(Console.Out);
tw.WriteDocType(name, pubid, sysid, subset);

Output

<myRoot>&lt;</myRoot>

In questo esempio di codice viene utilizzato il metodo WriteRaw e l'output presenta un carattere non valido come contenuto dell'elemento.

w.WriteStartElement("myRoot")
w.WriteRaw("<")
w.WriteEndElement()

w.WriteStartElement("myRoot");
w.WriteRaw("<");
w.WriteEndElement();

Output

<myRoot><</myRoot>

Nell'esempio seguente viene illustrato come convertire un documento XML da un documento incentrato sugli elementi a un documento incentrato sugli attributi.È inoltre possibile riconvertire un documento XML incentrato sugli attributi in un documento incentrato sugli elementi.La modalità incentrata sugli elementi implica che il documento XML è stato progettato per avere molti elementi e pochi attributi.Una progettazione incentrata sugli attributi presenta meno elementi e ciò che rappresenterebbe un elemento in una progettazione incentrata sugli elementi è stato trasformato in attributo degli elementi.Sono quindi presenti meno elementi, ma più attributi per elemento.

Questo esempio è utile se i dati XML sono stati progettati in una delle due modalità, in quanto ciò consentirà di convertirli nell'altra modalità.

Nel codice XML seguente viene utilizzato un documento incentrato sugli elementi.Gli elementi non contengono attributi.

Input - centric.xml

<?xml version='1.0' encoding='UTF-8'?>
<root>
    <Customer>
        <firstname>Jerry</firstname>
        <lastname>Larson</lastname>
        <Order>
        <OrderID>Ord-12345</OrderID>
          <OrderDetail>
            <Quantity>1301</Quantity>
            <UnitPrice>$3000</UnitPrice>
            <ProductName>Computer</ProductName>
          </OrderDetail>
        </Order>
    </Customer>
</root>

La seguente applicazione di esempio esegue la conversione.

// The program will convert an element-centric document to an 
// attribute-centric document or element-centric to attribute-centric.
using System;
using System.Xml;
using System.IO;
using System.Text;
using System.Collections;

class ModeConverter {
    private const int bufferSize=2048;

    internal class ElementNode {
        String _name;
        String _prefix;
        String _namespace;
        bool   _startElement;
        internal ElementNode() {
            this._name = null;
            this._prefix = null;
            this._namespace = null;
            this._startElement = false;
        }
        internal ElementNode(String prefix, String name, String nameSpace) {
            this._name = name;
            this._prefix = prefix;
            this._namespace = nameSpace;
        }
        public String name{
            get { return _name;   }
        }
        public String prefix{
            get { return _prefix;   }
        }
        public String nameSpace{
            get { return _namespace;   }
        }
        public bool startElement{
            get { return _startElement;   }
            set { _startElement = value;}
        }
    }
    public static void Main(String[] args) {
        ModeConverter modeConverter = new ModeConverter();
        if (args[0]== null || args[0]== "?" || args.Length < 2 ) {
            modeConverter.Usage();
            return;
        }
        FileStream sourceFile = new FileStream(args[1], FileMode.Open, FileAccess.Read, FileShare.Read);
        FileStream targetFile = new FileStream(args[2], FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
        if (args[0] == "-a") {
            modeConverter.ConertToAttributeCentric(sourceFile, targetFile);
        } else {
            modeConverter.ConertToElementCentric(sourceFile, targetFile);
        }
        return;
    }
    public void Usage() {
        Console.WriteLine("? This help message \n");
        Console.WriteLine("Convert -mode sourceFile, targetFile \n");
        Console.WriteLine("\t mode: e element centric\n");
        Console.WriteLine("\t mode: a attribute centric\n");
    }
    public void ConertToAttributeCentric(FileStream sourceFile, FileStream targetFile) {
        // Stack is used to track how many.
        Stack stack = new Stack();
        XmlTextReader reader = new XmlTextReader(sourceFile);
        reader.Read();
        XmlTextWriter writer = new XmlTextWriter(targetFile, reader.Encoding);
        writer.Formatting = Formatting.Indented;

        do {
            switch (reader.NodeType) {
                case XmlNodeType.XmlDeclaration:
                    writer.WriteStartDocument(null == reader.GetAttribute("standalone") || "yes" == reader.GetAttribute("standalone"));
                    break;

                case XmlNodeType.Element:
                    ElementNode element = new ElementNode(reader.Prefix, reader.LocalName, reader.NamespaceURI);

                    if (0 == stack.Count) {
                        writer.WriteStartElement(element.prefix, element.name, element.nameSpace);
                        element.startElement=true;
                    }

                    stack.Push(element);
                    break;

                case XmlNodeType.Attribute:
                    throw new Exception("We should never been here!");

                case XmlNodeType.Text:
                    ElementNode attribute = new ElementNode();
                    attribute = (ElementNode)stack.Pop();
                    element = (ElementNode)stack.Peek();
                    if (!element.startElement) {
                        writer.WriteStartElement(element.prefix, element.name, element.nameSpace);
                        element.startElement=true;
                    }
                    writer.WriteStartAttribute(attribute.prefix, attribute.name, attribute.nameSpace);
                    writer.WriteRaw(reader.Value);
                    reader.Read(); //jump over the EndElement
                    break;

                case XmlNodeType.EndElement:
                    writer.WriteEndElement();
                    stack.Pop();

                    break;

                case XmlNodeType.CDATA:
                    writer.WriteCData(reader.Value);
                    break;

                case XmlNodeType.Comment:
                    writer.WriteComment(reader.Value);
                    break;

                case XmlNodeType.ProcessingInstruction:
                    writer.WriteProcessingInstruction(reader.Name, reader.Value);
                    break;

                case XmlNodeType.EntityReference:
                    writer.WriteEntityRef( reader.Name);
                    break;

                case XmlNodeType.Whitespace:
                    writer.WriteWhitespace(reader.Value);
                    break;

                case XmlNodeType.None:
                    writer.WriteRaw(reader.Value);
                    break;

                case XmlNodeType.SignificantWhitespace:
                    writer.WriteWhitespace(reader.Value);
                    break;

                case XmlNodeType.DocumentType:
                    writer.WriteDocType(reader.Name, reader.GetAttribute("PUBLIC"), reader.GetAttribute("SYSTEM"), reader.Value);
                    break;

                case XmlNodeType.EndEntity:
                    break;


                default:
                    Console.WriteLine("UNKNOWN Node Type = " + ((int)reader.NodeType));
                    break;
             }
        } while (reader.Read());

        writer.WriteEndDocument();

        reader.Close();
        writer.Flush();
        writer.Close();
    }

    // Use the WriteNode to simplify the process.
    public void ConertToElementCentric(FileStream sourceFile, FileStream targetFile) {
        XmlTextReader reader = new XmlTextReader(sourceFile);
        reader.Read();
        XmlTextWriter writer = new XmlTextWriter(targetFile, reader.Encoding);
        writer.Formatting = Formatting.Indented;
        do {
            switch (reader.NodeType) {

                case XmlNodeType.Element:
                    writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
                    if (reader.MoveToFirstAttribute()) {
                         do {
                            writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
                            writer.WriteRaw(reader.Value);
                            writer.WriteEndElement();

                        } while(reader.MoveToNextAttribute());

                        writer.WriteEndElement();
                    }
                    break;

                case XmlNodeType.Attribute:
                     throw new Exception("We should never been here!");

                case XmlNodeType.Whitespace:
                    writer.WriteWhitespace(reader.Value);
                    break;

                case XmlNodeType.EndElement:
                    writer.WriteEndElement();
                    break;

                case XmlNodeType.Text:
                    throw new Exception("The input document is not a attribute centric document\n");

                default:
                    Console.WriteLine(reader.NodeType);
                    writer.WriteNode(reader, false);
                    break;
             }
        } while (reader.Read());

        reader.Close();
        writer.Flush();
        writer.Close();
    }
}

Dopo la compilazione del codice, è necessario eseguirlo dalla riga di comando digitando <nome compilato> -a centric.xml <nome file di output>. Il file di output deve essere disponibile e può essere un file di testo vuoto.

Per l'output seguente, supponendo che il programma C# sia stato compilato in centric_cs, la riga di comando è C:\centric_cs -a centric.xml centric_out.xml.

La modalità -a indica all'applicazione di eseguire la conversione del codice XML di input in codice incentrato sugli attributi, mentre la modalità -e indica di eseguire la conversione in codice incentrato sugli elementi.L'output seguente è il nuovo output incentrato sugli attributi generato tramite la modalità -a.Gli elementi contengono ora attributi invece di elementi annidati.

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>

<root>
<Customer firstname="Jerry" lastname="Larson">
 <Order OrderID="Ord-12345">
  <OrderDetail Quantity="1301" UnitPrice="$3000" ProductName="Computer" />
 </Order>
</Customer>
</root>

Mostra: