Jag bloggar numera på http://blog.dileno.com ».

Läsa och skriva XML i .NET

en ASP.NET-artikel av Martin S., publicerad den 18 maj 2005
XML är ett format som fungerar över ett flertal plattformar. Det är otroligt smidigt att i exempelvis Windows kunna skapa XML-filer som kan läsas i Mac OS X. I .NET-ramverket finns det ett gäng olika XML-objekt inbyggda som gör det enklare än tidigare att läsa och skriva XML-filer. Jag visar dig hur du kan implementera objekten XmlDocument och XmlTextWriter på ett enkelt sätt.

System.Xml


För att kunna använda sig av XML-objekten i .NET måste man importera namnområdet System.Xml där alla objekt finns. Vilka objekt namnområdet System.Xml tillhandahåller och vad respektive objekt är till för ser du här: System.Xml.

Presentation av data från XML-fil – xml.aspx


För att kunna presentera information från XML-filen vi ska använda oss av behöver vi en vanlig sida som ska se ut så här:


<%@ Page Language="VB" Strict="True" Debug="True" Inherits="def_" Src="xml.vb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Anmälningslista</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body { font: 12px Verdana,Arial,Helvetica,sans-serif; }
p { margin: 0 0 8px 0; }
form { width: 250px; }
legend { font-weight: bold; margin: 5px; }
</style>
</head>
<body>

<h1>Anmälda</h1>

<asp:literal id="lit_show" runat="server" />

<p>
<form name="def" method="post" runat="server">
<legend>Anmäl mig</legend>
<label for="xName">Namn:</label>
<p><asp:textbox id="xName" runat="server" /></p>
<p><asp:button id="new_reg" onclick="add_post" runat="server" text="Lägg till" /></p>
</form>
</p>

</body>
</html>

Högst upp på vår ASP.NET-sida talar vi i sedvanlig ordning om vilket språk vi använder oss av (VB.NET), anger två andra parametrar (Strict och Debug) samt ärver codebehind-filen med klassen def_ som vi ska använda oss av. För att kunna skriva ut innehållet från XML-filen vi ska använda oss av så använder vi oss av en literal. Sist har vi ett formulär för att vi ska kunna testa att skicka data som skrivs till XML-filen.

Att läsa och skriva ut XML-data


I codebehind-filen kommer det intressanta. Till att börja med importerar vi de namnområden vi kommer att använda:

Imports System
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Data
Imports Microsoft.VisualBasic
Imports System.IO
Imports System.Xml

Här är speciellt System.IO och System.Xml viktiga. System.IO (Input Output) sköter kommunikation till XML-filen vi ska använda och i System.Xml har vi de objekt vi behöver.

Sedan kommer vår klass (def_) där vi bland annat deklarerar objekt som ska användas på sidan:

'huvudklassen
public Class def_ : Inherits Page

protected withevents lit_show as literal
protected withevents xName as textbox
protected withevents xDt as textbox
protected withevents xSubmit as button

‘….
end class

I page_load() som körs när en sida laddas har vi koden som skriver ut informationen från XML-filen på webbsidan:

sub page_load()
'kolla om xml-filen finns
if file.exists(Server.MapPath("") & "/" & "reg.xml") then

'ladda xml-filen
dim xmldoc as new XmlDocument
xmldoc.Load(Server.MapPath("") & "/" & "reg.xml")

'plocka ut noden som innehåller datan som ska läsas
dim root as XmlElement = xmldoc.DocumentElement
dim children as XmlNodeList = root.SelectNodes("/Reg/Anmälda")
dim x as XmlNode

'loopa igenom noderna och skriv ut innehållet i dem
for each x in children
lit_show.text += x.FirstChild.InnerXml.toString() & " | " & x.LastChild.InnerXml.toString()
& "<br />"
next

end if

end sub

Till att börja med kollar vi om XML-filen finns. XML-filen heter reg.xml. Om XML-filen finns så skapar vi ett nytt XmlDocument-objekt och laddar XML-filen. För att kunna läsa från XML-filen så måste vi plocka ut noderna vi vill läsa av. Sedan loopar vi igenom noderna och skriver ut innehållet i dem i vår literal på webbsidan.
För att kunna loopa igenom noderna så måste vi skapa ett XmlNode-objekt och sedan gå igenom noderna som vi valt. För att skriva ut innehållet från noderna så använder vi oss av FirstChild och LastChild, InnerXml och gör om innehållet i noderna till strängformat.

Om en XML-nod ser ut enligt nedan så är FirstChild elementet Namn och LastChild elementet Datum:

<Anmälda>
<Namn>Martin Söderlund</Namn>
<Datum>2005-05-18 17:45:58</Datum>
</Anmälda>

Att skapa ett XML-dokument och skriva till det



Att skapa en XML-fil är inte så svårt. Man använder objektet FileStream tillsammans med XmlTextWriter och ett dataset. Koden nedan körs första gången XML-filen ska skapas.

'skapa nytt dataset
dim dsa as new DataSet("Reg")

sub add_post(sender as object,e as eventargs)

'kolla om filen existerar
if not file.exists(Server.MapPath("") & "/" & "reg.xml") then

dim filename as string
filename = Server.MapPath("") & "/" & "reg.xml"

dim myFileStream as new FileStream(filename,FileMode.Create)

dim myXmlWriter as new XmlTextWriter(myFileStream,Encoding.UTF8)
myXmlWriter.WriteStartDocument

dsa.WriteXml(myXmlWriter)

myXmlWriter.Close()

end if

‘…

end sub

Vi skapar ett nytt dataset som heter Reg. Vad datasetet heter blir vad rotelementet i XML-filen heter, vilket kan vara bra att veta när man sedan ska läsa information från XML-filen.

Hur som helst så kollar vi återigen om XML-filen finns för annars vore det ju ingen idé att skapa en ny XML-fil med samma namn. Om den reg.xml inte finns så anger vi sökvägen och namnet på XML-filen med hjälp av

dim filename as string
filename = Server.MapPath("") & "/" & "reg.xml"

Sedan använder vi objektet FileStream tillsammans med XmlTextWriter för att skapa XML-filen. Vi anger sökvägen och namnet på filen genom variabeln myFileStream och anger att kodningen av XML-filen ska vara i UTF-8. myXmlWriter.WriteStartDocument skriver första raden i XML-filen – den som talar om vilken version XML-filen är i (1.0) och vilken kodning filen har (UTF-8). Slutligen använder vi datasetet för att skapa själva XML-filen och sist så stänger vi objektet XmlWriter.

När XML-filen är skapad så vill man lägga till informationen i den. Det gör man genom att lägga till nya element:

'ladda en xml-fil
dim xmldoc as XmlDocument = new XmlDocument()
xmldoc.Load( Server.MapPath("") & "/" & "reg.xml" )

'skapa rotelementet
dim newelem as XmlNode = xmldoc.CreateNode(XmlNodeType.Element,"Anmälda","")
xmlDoc.DocumentElement.appendChild(newelem)

'skapa element
dim parentNode as XmlElement = xmldoc.CreateElement("Namn")
xmldoc.DocumentElement.LastChild.appendChild(parentNode)

dim UserText As XmlText = xmldoc.CreateTextNode(xName.Text)
parentNode.appendChild(UserText)

'skapa element
dim childNode as XmlElement = xmldoc.CreateElement("Datum")
xmldoc.DocumentElement.LastChild.appendChild(childNode)

dim DtText as XmlText = xmldoc.CreateTextNode(Now.toString())
childNode.appendChild(DtText)


'spara xml-filen
xmldoc.Save( Server.MapPath("") & "/" & "reg.xml" )

response.redirect("xml.aspx")

Först laddar vi XML-filen och skapar ett nytt rotelement (Anmälda) som vi sedan lägger till två element till (Namn och Datum). För att kunna skapa ett nytt rotelement så får vi använda oss av objektet XmlNode enligt ovan. För varje nytt element som ska läggas till under själva rotelementet så använder vi objektet XmlElement och objektet XmlDocuments metod CreateElement. För att lägga till information till respektive element så använder vi metoden appendChild() hos XmlElement.

Slutligen så sparar vi själva XML-filen och skickar tillbaka besökaren.

Kodlistning – xml.vb


Nedan följer kodlisning av hur xml.vb ser ut i sin helhet.

'importerar namnområden, så kallade namespace's
Imports System
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Data
Imports Microsoft.VisualBasic
Imports System.IO
Imports System.Xml


'huvudklassen
public Class def_ : Inherits Page

protected withevents lit_show as literal
protected withevents xName as textbox
protected withevents xDt as textbox
protected withevents xSubmit as button


sub page_load()

'kolla om xml-filen finns
if file.exists(Server.MapPath("") & "/" & "reg.xml") then

'ladda xml-filen
dim xmldoc as new XmlDocument
xmldoc.Load(Server.MapPath("") & "/" & "reg.xml")

'plocka ut noden som innehåller datan som ska läsas
dim root as XmlElement = xmldoc.DocumentElement
dim children as XmlNodeList = root.SelectNodes("/Reg/Anmälda")
dim x as XmlNode

'loopa igenom noderna och skriv ut innehållet i dem
for each x in children
lit_show.text += x.FirstChild.InnerXml.toString() & " | " & x.LastChild.InnerXml.toString()
& "<br />"
next

end if

end sub


'skapa nytt dataset
dim dsa as new DataSet("Reg")


sub add_post(sender as object,e as eventargs)

'kolla om filen existerar
if not file.exists(Server.MapPath("") & "/" & "reg.xml") then

dim filename as string
filename = Server.MapPath("") & "/" & "reg.xml"

dim myFileStream as new FileStream(filename,FileMode.Create)

dim myXmlWriter as new XmlTextWriter(myFileStream,Encoding.UTF8)
myXmlWriter.WriteStartDocument

dsa.WriteXml(myXmlWriter)

myXmlWriter.Close()

end if


'ladda en xml-fil
dim xmldoc as XmlDocument = new XmlDocument()
xmldoc.Load( Server.MapPath("") & "/" & "reg.xml" )

'skapa rotelementet
dim newelem as XmlNode = xmldoc.CreateNode(XmlNodeType.Element,"Anmälda","")
xmlDoc.DocumentElement.appendChild(newelem)

'skapa element
dim parentNode as XmlElement = xmldoc.CreateElement("Namn")
xmldoc.DocumentElement.LastChild.appendChild(parentNode)

dim UserText As XmlText = xmldoc.CreateTextNode(xName.Text)
parentNode.appendChild(UserText)

'skapa nytt element
dim childNode as XmlElement = xmldoc.CreateElement("Datum")
xmldoc.DocumentElement.LastChild.appendChild(childNode)

dim DtText as XmlText = xmldoc.CreateTextNode(Now.toString())
childNode.appendChild(DtText)


'spara xml-filen
xmldoc.Save( Server.MapPath("") & "/" & "reg.xml" )

response.redirect("xml.aspx")

end sub


end class

Ladda ner filerna


Du kan ladda ner xml.aspx och xml.vb här: Ladda ner exempelfilerna. (zip-fil, 1.7 kb)

Slutligen


Som du ser är det en hel del olika objekt som ska arbeta ihop. Det bästa är att läsa om respektive objekt på MSDN och titta på exempel som finns där. Just denna metod för att läsa och skriva till XML-filer är bara en av flera – det är det enkelt att använda andra objekt i System.Xml för att utföra samma saker och jag rekommenderar dig att testa dig fram för att se vad som passar dig bäst.