Lezen in het Engels

Delen via


Voorbeelden van XML-serialisatie

XML-serialisatie kan meerdere vormen aannemen, van eenvoudig tot complex. U kunt bijvoorbeeld een klasse serialiseren die eenvoudigweg bestaat uit openbare velden en eigenschappen, zoals wordt weergegeven in Inleiding tot XML-serialisatie. In de volgende codevoorbeelden worden verschillende geavanceerde scenario's besproken, waaronder het gebruik van XML-serialisatie om een XML-stroom te genereren die voldoet aan een specifiek XSD-document (XML Schema).

Een dataset serialiseren

Naast het serialiseren van een exemplaar van een openbare klasse, kunt u ook een exemplaar van een DataSet, zoals wordt weergegeven in het volgende codevoorbeeld, serialiseren:

private void SerializeDataSet(string filename)
{
    XmlSerializer ser = new XmlSerializer(typeof(DataSet));

    // Creates a DataSet; adds a table, column, and ten rows.
    DataSet ds = new DataSet("myDataSet");
    DataTable t = new DataTable("table1");
    DataColumn c = new DataColumn("thing");
    t.Columns.Add(c);
    ds.Tables.Add(t);
    DataRow r;

    for (int i = 0; i < 10; i++) {
        r = t.NewRow();
        r[0] = "Thing " + i;
        t.Rows.Add(r);
    }

    TextWriter writer = new StreamWriter(filename);
    ser.Serialize(writer, ds);
    writer.Close();
}

Een XmlElement en XmlNode serialiseren

U kunt ook exemplaren van een XmlElement of XmlNode klasse serialiseren, zoals wordt weergegeven in het volgende codevoorbeeld:

private void SerializeElement(string filename)
{
    XmlSerializer ser = new XmlSerializer(typeof(XmlElement));
    XmlElement myElement = new XmlDocument().CreateElement("MyElement", "ns");
    myElement.InnerText = "Hello World";
    TextWriter writer = new StreamWriter(filename);
    ser.Serialize(writer, myElement);
    writer.Close();
}

private void SerializeNode(string filename)
{
    XmlSerializer ser = new XmlSerializer(typeof(XmlNode));
    XmlNode myNode = new XmlDocument().
    CreateNode(XmlNodeType.Element, "MyNode", "ns");
    myNode.InnerText = "Hello Node";
    TextWriter writer = new StreamWriter(filename);
    ser.Serialize(writer, myNode);
    writer.Close();
}

Een klasse serialiseren die een veld bevat dat een complex object retourneert

Als een eigenschap of veld een complex object retourneert (zoals een matrix of een klasse-exemplaar), wordt dit XmlSerializer geconverteerd naar een element dat is genest in het hoofd-XML-document. De eerste klasse in het volgende codevoorbeeld retourneert bijvoorbeeld een exemplaar van de tweede klasse:

public class PurchaseOrder
{
    public Address MyAddress;
}

public record Address
{
    public string FirstName;
}

De geserialiseerde XML-uitvoer kan er als volgt uitzien:

<PurchaseOrder>
    <MyAddress>
        <FirstName>George</FirstName>
    </MyAddress>
</PurchaseOrder>

Een matrix met objecten serialiseren

U kunt ook een veld serialiseren dat een matrix met objecten retourneert, zoals wordt weergegeven in het volgende codevoorbeeld:

public class PurchaseOrder
{
    public Item [] ItemsOrders;
}

public class Item
{
    public string ItemID;
    public decimal ItemPrice;
}

Als er twee items zijn geordend, kan het geserialiseerde klasse-exemplaar eruitzien als de volgende code:

<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <ItemsOrders>
        <Item>
            <ItemID>aaa111</ItemID>
            <ItemPrice>34.22</ItemPrice>
        </Item>
        <Item>
            <ItemID>bbb222</ItemID>
            <ItemPrice>2.89</ItemPrice>
        </Item>
    </ItemsOrders>
</PurchaseOrder>

Een klasse serialiseren die de ICollection-interface implementeert

U kunt uw eigen verzamelingsklassen maken door de ICollection interface te implementeren en exemplaren XmlSerializer van deze klassen te serialiseren.

Notitie

Wanneer een klasse de ICollection interface implementeert, wordt alleen de verzameling die door de klasse is opgenomen geserialiseerd. Openbare eigenschappen of velden die aan de klasse worden toegevoegd, worden niet geserialiseerd. Als u wilt worden geserialiseerd, moet de klasse een methode Toevoegen en een itemeigenschap (C#-indexeerfunctie) bevatten.

using System;
using System.Collections;
using System.IO;
using System.Xml.Serialization;

public class Test
{
    static void Main()
    {
        Test t = new Test();
        t.SerializeCollection("coll.xml");
    }

    private void SerializeCollection(string filename)
    {
        Employees Emps = new Employees();
        // Note that only the collection is serialized -- not the
        // CollectionName or any other public property of the class.
        Emps.CollectionName = "Employees";
        Employee John100 = new Employee("John", "100xxx");
        Emps.Add(John100);
        XmlSerializer x = new XmlSerializer(typeof(Employees));
        TextWriter writer = new StreamWriter(filename);
        x.Serialize(writer, Emps);
    }
}

public class Employees : ICollection
{
    public string CollectionName;
    private ArrayList empArray = new ArrayList();

    public Employee this[int index] => (Employee) empArray[index];

    public void CopyTo(Array a, int index)
    {
        empArray.CopyTo(a, index);
    }
    
    public int Count => empArray.Count;
    
    public object SyncRoot => this;
    
    public bool IsSynchronized => false;
    
    public IEnumerator GetEnumerator() => empArray.GetEnumerator();

    public void Add(Employee newEmployee)
    {
        empArray.Add(newEmployee);
    }
}

public class Employee
{
    public string EmpName;
    public string EmpID;
    
    public Employee() {}
    
    public Employee(string empName, string empID)
    {
        EmpName = empName;
        EmpID = empID;
    }
}

Voorbeeld van inkooporder

U kunt de volgende voorbeeldcode knippen en plakken in een tekstbestand en de naam ervan wijzigen met een .cs of .vb bestandsnaamextensie. Gebruik de C# of Visual Basic-compiler om het bestand te compileren. Voer het vervolgens uit met de naam van het uitvoerbare bestand.

In dit voorbeeld wordt een eenvoudig scenario gebruikt om te laten zien hoe een exemplaar van een object wordt gemaakt en geserialiseerd in een bestandsstroom met behulp van de Serialize methode. De XML-stroom wordt opgeslagen in een bestand. Hetzelfde bestand wordt vervolgens gelezen en gereconstrueerd in een kopie van het oorspronkelijke object met behulp van de Deserialize methode.

In dit voorbeeld wordt een klasse met de naam PurchaseOrder geserialiseerd en vervolgens gedeserialiseerd. Een tweede klasse met de naam Address is ook opgenomen omdat het openbare veld met de naam ShipTo moet worden ingesteld op een Address. Op dezelfde manier wordt een OrderedItem klasse opgenomen omdat een matrix met OrderedItem objecten moet worden ingesteld op het OrderedItems veld. Ten slotte bevat een klasse met de naam Test de code waarmee de klassen worden geserialiseerd en gedeserialiseerd.

Met de CreatePO methode worden de PurchaseOrder, Addressen klasseobjecten gemaakt OrderedItem en worden de waarden van het openbare veld ingesteld. De methode bouwt ook een exemplaar van de XmlSerializer klasse die wordt gebruikt om de PurchaseOrderklasse te serialiseren en deserialiseren.

Notitie

De code geeft het type klasse door dat wordt geserialiseerd aan de constructor. Met de code wordt ook een FileStream xml-stroom gemaakt die wordt gebruikt om de XML-stroom naar een XML-document te schrijven.

De ReadPo methode is iets eenvoudiger. Er worden alleen objecten gemaakt om hun waarden te deserialiseren en uit te lezen. Net als bij de CreatePo methode moet u eerst een XmlSerializer, waarbij het type klasse wordt gedeserialiseerd doorgegeven aan de constructor. Er is ook een FileStream vereiste om het XML-document te lezen. Als u deserialiseren van de objecten, roept u de Deserialize methode aan met het FileStream argument. Het gedeserialiseerde object moet worden gecast naar een objectvariabele van het type PurchaseOrder. De code leest vervolgens de waarden van de gedeserialiseerde PurchaseOrder.

Notitie

U kunt het PO.xml-bestand lezen dat is gemaakt om de werkelijke XML-uitvoer te bekijken.

using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

// The XmlRoot attribute allows you to set an alternate name
// (PurchaseOrder) for the XML element and its namespace. By
// default, the XmlSerializer uses the class name. The attribute
// also allows you to set the XML namespace for the element. Lastly,
// the attribute sets the IsNullable property, which specifies whether
// the xsi:null attribute appears if the class instance is set to
// a null reference.
[XmlRoot("PurchaseOrder", Namespace="http://www.cpandl.com",
IsNullable = false)]
public class PurchaseOrder
{
    public Address ShipTo;
    public string OrderDate;
    // The XmlArray attribute changes the XML element name
    // from the default of "OrderedItems" to "Items".
    [XmlArray("Items")]
    public OrderedItem[] OrderedItems;
    public decimal SubTotal;
    public decimal ShipCost;
    public decimal TotalCost;
}

public class Address
{
    // The XmlAttribute attribute instructs the XmlSerializer to serialize the
    // Name field as an XML attribute instead of an XML element (XML element is
    // the default behavior).
    [XmlAttribute]
    public string Name;
    public string Line1;

    // Setting the IsNullable property to false instructs the
    // XmlSerializer that the XML attribute will not appear if
    // the City field is set to a null reference.
    [XmlElement(IsNullable = false)]
    public string City;
    public string State;
    public string Zip;
}

public class OrderedItem
{
    public string ItemName;
    public string Description;
    public decimal UnitPrice;
    public int Quantity;
    public decimal LineTotal;

    // Calculate is a custom method that calculates the price per item
    // and stores the value in a field.
    public void Calculate()
    {
        LineTotal = UnitPrice * Quantity;
    }
}

public class Test
{
    public static void Main()
    {
        // Read and write purchase orders.
        Test t = new Test();
        t.CreatePO("po.xml");
        t.ReadPO("po.xml");
    }

    private void CreatePO(string filename)
    {
        // Creates an instance of the XmlSerializer class;
        // specifies the type of object to serialize.
        XmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder));
        TextWriter writer = new StreamWriter(filename);
        PurchaseOrder po =new PurchaseOrder();

        // Creates an address to ship and bill to.
        Address billAddress = new Address();
        billAddress.Name = "Teresa Atkinson";
        billAddress.Line1 = "1 Main St.";
        billAddress.City = "AnyTown";
        billAddress.State = "WA";
        billAddress.Zip = "00000";
        // Sets ShipTo and BillTo to the same addressee.
        po.ShipTo = billAddress;
        po.OrderDate = System.DateTime.Now.ToLongDateString();

        // Creates an OrderedItem.
        OrderedItem i1 = new OrderedItem();
        i1.ItemName = "Widget S";
        i1.Description = "Small widget";
        i1.UnitPrice = (decimal) 5.23;
        i1.Quantity = 3;
        i1.Calculate();

        // Inserts the item into the array.
        OrderedItem [] items = {i1};
        po.OrderedItems = items;
        // Calculate the total cost.
        decimal subTotal = new decimal();
        foreach(OrderedItem oi in items)
        {
            subTotal += oi.LineTotal;
        }
        po.SubTotal = subTotal;
        po.ShipCost = (decimal) 12.51;
        po.TotalCost = po.SubTotal + po.ShipCost;
        // Serializes the purchase order, and closes the TextWriter.
        serializer.Serialize(writer, po);
        writer.Close();
    }

    protected void ReadPO(string filename)
    {
        // Creates an instance of the XmlSerializer class;
        // specifies the type of object to be deserialized.
        XmlSerializer serializer = new XmlSerializer(typeof(PurchaseOrder));
        // If the XML document has been altered with unknown
        // nodes or attributes, handles them with the
        // UnknownNode and UnknownAttribute events.
        serializer.UnknownNode+= new
        XmlNodeEventHandler(serializer_UnknownNode);
        serializer.UnknownAttribute+= new
        XmlAttributeEventHandler(serializer_UnknownAttribute);

        // A FileStream is needed to read the XML document.
        FileStream fs = new FileStream(filename, FileMode.Open);
        // Declares an object variable of the type to be deserialized.
        PurchaseOrder po;
        // Uses the Deserialize method to restore the object's state
        // with data from the XML document. */
        po = (PurchaseOrder) serializer.Deserialize(fs);
        // Reads the order date.
        Console.WriteLine ("OrderDate: " + po.OrderDate);

        // Reads the shipping address.
        Address shipTo = po.ShipTo;
        ReadAddress(shipTo, "Ship To:");
        // Reads the list of ordered items.
        OrderedItem [] items = po.OrderedItems;
        Console.WriteLine("Items to be shipped:");
        foreach(OrderedItem oi in items)
        {
            Console.WriteLine("\t"+
            oi.ItemName + "\t" +
            oi.Description + "\t" +
            oi.UnitPrice + "\t" +
            oi.Quantity + "\t" +
            oi.LineTotal);
        }
        // Reads the subtotal, shipping cost, and total cost.
        Console.WriteLine(
        "\n\t\t\t\t\t Subtotal\t" + po.SubTotal +
        "\n\t\t\t\t\t Shipping\t" + po.ShipCost +
        "\n\t\t\t\t\t Total\t\t" + po.TotalCost
        );
    }

    protected void ReadAddress(Address a, string label)
    {
        // Reads the fields of the Address.
        Console.WriteLine(label);
        Console.Write("\t"+
        a.Name +"\n\t" +
        a.Line1 +"\n\t" +
        a.City +"\t" +
        a.State +"\n\t" +
        a.Zip +"\n");
    }

    protected void serializer_UnknownNode
    (object sender, XmlNodeEventArgs e)
    {
        Console.WriteLine("Unknown Node:" +   e.Name + "\t" + e.Text);
    }

    protected void serializer_UnknownAttribute
    (object sender, XmlAttributeEventArgs e)
    {
        System.Xml.XmlAttribute attr = e.Attr;
        Console.WriteLine("Unknown attribute " +
        attr.Name + "='" + attr.Value + "'");
    }
}

De XML-uitvoer kan er als volgt uitzien:

<?xml version="1.0" encoding="utf-8"?>
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.cpandl.com">
    <ShipTo Name="Teresa Atkinson">
        <Line1>1 Main St.</Line1>
        <City>AnyTown</City>
        <State>WA</State>
        <Zip>00000</Zip>
    </ShipTo>
    <OrderDate>Wednesday, June 27, 2001</OrderDate>
    <Items>
        <OrderedItem>
            <ItemName>Widget S</ItemName>
            <Description>Small widget</Description>
            <UnitPrice>5.23</UnitPrice>
            <Quantity>3</Quantity>
            <LineTotal>15.69</LineTotal>
        </OrderedItem>
    </Items>
    <SubTotal>15.69</SubTotal>
    <ShipCost>12.51</ShipCost>
    <TotalCost>28.2</TotalCost>
</PurchaseOrder>

Zie ook


Aanvullende resources

Documentatie

Training

Module

JSON-bestanden opslaan en ophalen - Training

Meer informatie over het serialiseren en deserialiseren van JSON-tekenreeksen (JavaScript Object Notation) met behulp van de JsonSerializer-klasse, de klasse JsonSerializerOptions en Gegevensoverdrachtobjecten.