Utisci korisnika

"Želim da kazem da iako sam tek na pola, da sam oduševljena ovim načinom na koji stvari funkcionisu!" Stanislava Kraguljac, Beograd

Pre svega želim da vam se zahvalim na veoma brzom i profesionalnom pristupu. Jovan Knežević - Hong Kong


Kompletna lista utisaka

Testiranje online

Arhitektura računara

Za one koji žele da znaju više.

Windows OS

Ovo bi svakako trebalo da probate.

Odnosi s javnošću

Koliko znate PR?

Pogledajte još neke od testova

Newsletter

Ukoliko želite da Vas redovno obaveštavamo o novostima sa Link eLearning sajta prijavite se na našu newsletter listu.

Ime:

Prezime:

Email:


Anketa

Arhiva anketa

BAZA ZNANJA


Kurs: XML tehnologije i veb servisi

Modul: XML tehnologije

Autor: Vladimir Marić

Naziv jedinice: DOM XML


Materijali vezani uz ovu lekciju:

- Test dom xml
- DOM XML (PDF dokument)



DOM XML je koncept koji podrazumeva pregled i rukovanje XML dokumentom kroz Document Object Model. Ono što je karakteristično za DOM jeste određeni set metoda, koje su iste nezavisno od okruženja u kome se dokumentom rukuje.

Na primer, DOM metodi getElementById, getElementsByTagName koje ćemo koristiti u primerima, takođe karakterišu realizaciju DOM-a i u drugim jezicima, pa se može reći da ovo predstavlja univerzalan koncept rukovanja XML-om. DOM se u C#-u realizuje kroz klasu XmlDocument.

Za primer, rukovaćemo dokumentom iz prethodne lekcije.

 

Kreiranje i upis u XML dokument

Da bismo rukovali DOM XML objektom, potreban nam je objekat klase XmlDocument:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<root></root>");

 

Nakon kreiranja XmlDocument objekta, potrebno je da kreiramo ili preuzmemo njegovu strukturu. Ako preuzimamo strukturu (kroz tok (Stream) ili iz fajla), koristimo metod Load, dok, ukoliko formiramo strukturu iz početka, koristimo metod LoadXml, koji prihvata string.

xmlDoc.LoadXml("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><izdanja></izdanja>");

 

Nakon obrade, dokument snimamo na fajl sistem metodom Save:

xmlDoc.Save(@"c:\mojXml.xml");

 

Kada imamo formiran dokument, za korenim elementom, podelementima rukujemo po sistemu roditelja i dece elemenata. Na primer, ukoliko bismo hteli da dodamo jedan podelement elementu root, morali bismo prvo naći sam Root element, a zatim mu dodavati decu čvorove (Node).

Za pretragu dokumenta možemo koristiti više metoda. Jedna od njih je GetElementsByTagName. Na ovaj način, dobićemo niz podelemenata elementa određenog naziva. S obzirom na to da imamo samo jedan koreni element, izdanja, lako ćemo doći do njega:

XmlNode root = xmlDoc.GetElementsByTagName("izdanja")[0];

 

Metodom GetElementsByTagName(„izdanja") dobijamo sve tagove sa nazivom izdanja. S obzirom na to da ima samo jedan, sigurni smo da se taj element nalazi pod indeksom 0.

Da bismo dodali neki podelement nekom elementu, moramo ga prvo kreirati na nivou dokumenta metodom CreateElement, a zatim dodati željenom elementu, metodom AppendChild tog elementa. S bzirom na to da želimo da napravimo listu izdanja, napisaćemo:

XmlElement izdanje = xmlDoc.CreateElement("izdanje");
root.AppendChild(izdanje);

 

Nakon ovoga promenljiva izdanje ima isti tretman kao i bilo koji drugi element. Pre nego što dodamo podelemente elementu izdanje, dodaćemo mu i dva potrebna atributa: id i isbn. Atributi se, takođe, kreiraju na nivou dokumenta, a zatim dodaju željenim elementima, metodom Append svojstva Attributes.

XmlAttribute idAtribut = xmlDoc.CreateAttribute("id");
atribut.Value = "1";
izdanje.Attributes.Append(idAtribut);

 

Zatim možemo kreirati i podelemente elementa izdanje:

XmlElement autor = xmlDoc.CreateElement("autor");
autor.InnerText = "Milorad Pavic";
izdanje.AppendChild(autor);

 

Jedina nepoznanica u ovom delu koda je InnerText svojstvo elementa, koje zapravo predstavlja njegov sadržaj.

Na isti način možemo kreirati i element naslov.

Evo kako bi izgledao kompletan primer (podrazumeva se da postoji klasa Izdanje).

List<Izdanje> izdanja = new List<Izdanje>();
izdanja.Add(new Izdanje(1,"Predeo slikan cajem","Milorad Pavic","1111"));
izdanja.Add(new Izdanje(2, "Mnogo buke ni oko cega", "Viljem Sekspir", "2222"));

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><root></root>");
XmlNode root = xmlDoc.GetElementsByTagName("root")[0];

foreach (Izdanje izd in izdanja)
{
    XmlElement izdanje = xmlDoc.CreateElement("izdanje");
    XmlAttribute idAtribut = xmlDoc.CreateAttribute("id");
    idAtribut.Value = izd.id.ToString();
    XmlAttribute isbnAtribut = xmlDoc.CreateAttribute("isbn");
    isbnAtribut.Value = izd.isbn.ToString();
    izdanje.Attributes.Append(idAtribut);
    izdanje.Attributes.Append(isbnAtribut);
    XmlElement autor = xmlDoc.CreateElement("autor");
    autor.InnerText = izd.autor.ToString();
    izdanje.AppendChild(autor);
    XmlElement naslov = xmlDoc.CreateElement("naslov");
    naslov.InnerText = izd.naslov.ToString();
    izdanje.AppendChild(naslov);
    root.AppendChild(izdanje);
}
xmlDoc.Save(@"c:\mojXml.xml");

 

Čitanje i parsiranje XML dokumenta

Parsiranje DOM XML-a je veoma bitno znati jer je ovaj koncept veoma često korišćen, ne samo u C#, već i u drugim jezicima. Naročitu popularnost DOM koncept ima u JavaScriptu.

Preuzimanje XML DOM dokumenta iz fajla se postiže na sličan način kao i iz stringa:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(@"c:\mojXml.xml");

Kada je dokument učitan, koristimo razne tehnike da izolujemo njegove elemente. Na primer, ako želimo da preuzmemo sva izdanja, napisaćemo:

XmlNodeList svaIzdanja = xmlDoc.GetElementsByTagName("izdanje");

Metod GetElementsBaTagName vratio je sve elemente (čvorove) čiji je naziv izdanje. Zatim možemo pregledati sadržaje svih dobijenih čvorova:

foreach(XmlElement izdanje in svaIzdanja)
 Console.WriteLine(izdanje.InnerXml);

Primećujemo pojmove XmlNode i XmlElement. Bitna razlika između ova dva tipa podatka ogleda se u tome što XmlNode ne sadrži metode za pretraživanje, pa je, ako hoćemo da vršimo dublju pretragu čvora, potrebno da ga tretiramo kao element. Što smo i uradili u prethodnom kodu. Sada možemo izvršiti još dublju pretragu, na nivou svakog elementa i na primer, prikazati sve naslove:

foreach (XmlElement izdanje in svaIzdanja)
      foreach(XmlElement naslov in izdanje.GetElementsByTagName("naslov"))
            Console.WriteLine(naslov.InnerText);


Umesto sekvencijalnog pretraživanja, preuzimanjem liste čvorova određenog imena, možemo izvršiti i precizniju pretragu metodom GetElementById, pri čemu se podrazumeva da određeni element poseduje atribut id. Takođe, da bi metod GetElementById bio funkcionalan, potrebno je da id bude pravilno definisan u definiciji dokumenta, tako da je pre primera sa pretragom po id-u, potrebno modifikovati i sam XML fajl, dodavanjem definicije:

<!DOCTYPE izdanja [
<!ELEMENT izdanja ANY>
<!ELEMENT izdanje ANY>
<!ELEMENT autor EMPTY>
<!ELEMENT naslov EMPTY>
<!ATTLIST izdanje id ID #REQUIRED>]>

 

Sledeći primer treba da prikaže naslov i autora izdanja čiji je ID 1.

XmlElement knjiga1 = xmlDoc.GetElementById("1");
Console.WriteLine("Naslov: " + knjiga1.GetElementsByTagName("naslov")[0].InnerXml);
Console.WriteLine("Autor: " + knjiga1.GetElementsByTagName("autor")[0].InnerXml);

 

Atributi jednog elementa nalaze se u svojstvima tog elementa pod nazivom Attributes. Ovo je klasična kolekcija (XmlAttributesCollection), pa se tako njenim članovima može pristupati putem indeksa ili ključa. Id elementa knjiga1 iz primera, dobili bismo na jedan od sledeća dva načina:

knjiga1.Attributes[0].Value

ili

knjiga1.Attributes["id"].Value


Kada se jednom domognemo čvora, ukoliko smo sigurni da je odgovarajući, možemo vršiti i navigaciju relativno, u odnosu na taj čvor. Pri čemu se možemo kretati naviše u hijerarhiji (kroz „pretke” čvora) ili naniže, kroz "potomke" čvora.

Za ovu navigaciju koristimo svojstva: ParentNode, ChildNodes, NextSibling, PreviousSibling, LastChild...

Pogledajmo nekoliko primera (podrazumevaju da promenljiva knjiga1 sadrži element izdanje):

Umesto malopređašnjeg traženja uz pomoć metode GetElementsByTagName, mogli smo takođe upotrebiti i svojstvo ChildNodes. S obzirom na to da element izdanje sadrži dva podelementa, lako možemo doći do autora i naslova:

Console.WriteLine("Naslov: " + knjiga1.ChildNodes[0].InnerText);
Console.WriteLine("Autor: " + knjiga1.ChildNodes[1].InnerText);


Očigledno je da ChildNodes sadrži kolekciju čvorova od kojih odgovarajuće dobijamo unosom indeksa te kolekcije.

Isti rezultat mogli smo dobiti i sledećim kodom:

Console.WriteLine("Naslov: " + knjiga1.FirstChild.InnerText);
Console.WriteLine("Autor: " + knjiga1.FirstChild.NextSibling.InnerText);


U ovom slučaju, ne ciljamo elemente direktno, već se krećemo po hijerarhiji. Prvo se pozicioniramo na prvi "dete" element, elementa izdanje, a zatim i na njegovog prvog sledećeg "brata".

 

Modifikacija nodova i događaji

Svojstva u prethodnim primerima, osim čitanja, omogućavaju i upis vrednosti u elemente. Ovaj upis vrši se na isti način kao i čitanje. Dodelom vrenodsti. Recimo da želimo da izmenimo autora i naslov knjige:

knjiga1.FirstChild.InnerText = "Mansarda";
knjiga1.FirstChild.NextSibling.InnerText = "Danilo Kiš";


Naravno, da bi ovaj primer imao bilo kakav efekat, moramo izmenjeni dokument i snimiti:

xmlDoc.Save(@"c:\mojXml.xml");


Takođe, možemo angažovati i određene događaje prilikom intervencija na dokumentu uz pomoć rukovalaca događajima XmlDocument objekta. Na primer, ako bismo želeli da pratimo sve izmene u aktuelnom dokumentu, postavili bismo rukovaoca događajima NodeChanged.

xmlDoc.NodeChanged+=new XmlNodeChangedEventHandler(xmlDoc_NodeChanged);


Sam metod za rukovanje događajima kao pošiljaoca (Sender) prihvata kompletan XmlDocument objekat, ali u argumentima događaja XmlNodeChangedEventArgs, nalazi se široka paleta svojstava, pa čak i sam čvor na kome se događaj izvršio.

static void xmlDoc_NodeChanged(object sender, XmlNodeChangedEventArgs e)
{
Console.WriteLine("Izmena noda " + e.Node.ParentNode.Name + " " + e.OldValue + " je promenjeno u " + e.NewValue);
}

 

Osim NodeChanged događaja, moguće je još obraditi i NodeChanging, NodeInserting, NodeInserted, NodeRemoving i NodeRemoved događaje.

 

Najvažnije iz lekcije:

  1. XmlDocument podrazumeva rukovanje XML-om kroz Document Object Model.
  2. DOM je generalni koncept i nije striktno vezan samo za C# i XmlDocument klasu.
  3. U XmlDocument-u XML se u vidu stringa učitava uz pomoć LoadXml metode, a u vidu fajla uz pomoć metode Load.
  4. Snimanje XML dokumenta u fajl vrši se metodom Save.
  5. Tekstualni sadržaj svakog čvora moguće je videti kroz svojstvo InnerText.
  6. Xml sadržaj svakog čvora moguće je videti kroz svojstvo InnerXml.
  7. Pretraga u XmlDocument objektu se može vršiti sekvencijalno, uz pomoć svojstava i metoda za navigaciju (ChildNodes, NextSibling, PreviousSibling, FirstChild) ili direktno, metodama za pretragu (GetElementsByTagName, GetElementById...).
  8. Moguće je rukovati događajima XmlDocument objekta.
  9. Upis podataka u XmlDocument vrši se metodama CreateElement i CreateAttribute, kao i metodama AppendChild i Attributes.Append.
  10. Atributi elementa se nalaze u kolekciji Attributes na nivou tog elementa.

 

Vežba 1

Problem:

Potrebno je napraviti konzolnu aplikaciju koja prihvata korisnički unos, liniju po liniju. Svaka linija, predstavlja jedan element XML dokumenta i svaki od elemenata poseduje jedinstveni atribut id, koji generiše sama aplikacija.

Kada korisnik unese praznu liniju (samo pritisne enter), program se zaustavlja i XML dokument se upisuje na fajl sistem.

 

Rešenje:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml("<root></root>");
            XmlNode root = xdoc.GetElementsByTagName("root")[0];
            string el = Console.ReadLine();
            int counter = 1;
            while (el != string.Empty)
                {
                    XmlElement myNewEl = xdoc.CreateElement("myElement");
                    XmlAttribute idAttr = xdoc.CreateAttribute("id");
                    idAttr.Value = counter.ToString();
                    myNewEl.Attributes.Append(idAttr);
                    myNewEl.InnerText = el;
                    root.AppendChild(myNewEl);
                    el = Console.ReadLine();
                    counter++;
                }
            xdoc.Save("myXmlDoc.xml");
        }
    }
}

 

Vežba 2

Problem:

Dat je sledeći XML dokument koji se nalazi u fajlu myXmlDoc1.xml

<?xml version="1.0" encoding="utf-8" ?>
<html>
  <head>
    <title>My Hello page</title>
    <meta name="description" content="This is my hello page"/>
    <meta name="keywords" content="hello, page"/>
  </head>
  <body>
    Hello!
  </body>
</html>

 

Potrebno je sadržaj meta description taga emitovati na izlaz.

 

Rešenje:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument xdoc = new XmlDocument();
            xdoc.Load("myXmlDoc1.xml");
            XmlNodeList metas = xdoc.GetElementsByTagName("meta");
            foreach (XmlNode meta in metas)
                {
                    if(meta.Attributes["name"].Value=="description")
Console.WriteLine(meta.Attributes["content"].Value.ToString());
                }
        }
    }
}


Smatrate da je ova lekcija korisna?  Preporučite je. Broj preporuka:0


Molimo Vas unesite svoje podatke i dobićete pristup besplatnim lekcijama.

Ime: 
Prezime: 
Email: