[ CallMeSaMaster @ 14.12.2009. 13:57 ] @
Pozdrav,

moze li mi neko pomoci, kako da uradim sledece:

Imam XML file:

Code:


<?xml version="1.0" encoding="UTF-8"?>
<Obrada xmlns="urn:OsobaA.xsd">
  <DatumPrijave>
    <Datum>2009-12-11</Datum>
  </DatumPrijave>
  <OsobaA>
    <Podaci>
      <Godina>2009</Godina>
    </Podaci>
  </OsobaA>
  <OsobaA>
    <Podaci>
      <Godina>2007</Godina>
    </Podaci>
  </OsobaA>
  <OsobaB>
    <Podaci>
      <Godina>2001</Godina>
    </Podaci>
  </Osobab>
</Obrada>


DatumPrijave se sadrzi samo jednom u cijelom XML-u dok podaci o osobi (OsobaA) mogu biti visestruki.

1. Kako da selecktujem samo Datum iz DatumPrijave?
2. Kako da pokupim podatke iz Nodova <OsobaA>? Problem je u tome sto ovdej moze biti razlicitih dojelova npr. OsobaA, OsobaB, OsobaC itd. Ja bih htio da kazem da mi recimo vrati sve podatke iz OsobaA - nesto tipa LIKE u SQL. Npr da mi da sve podatke cije ime noda pocinje recimo sa "OSOBA". Da li je ovo moguce?

Moze li neko pomoci

Pozdrav
[ malo_nj @ 14.12.2009. 17:39 ] @
Mogao samo izmjeni xml imas par gresaka dva puta osobaA i /OsobaB case sensitive je
[ CallMeSaMaster @ 14.12.2009. 18:24 ] @
Nisam te bas najbolje shvatio sta si htio reci, ali upravo mi tako i treba. OsobaA moze postojati x-puta kao i bilo koja druga osoba odnosno tip osobe. Pogledat cu code svakako...Hvala
[ Igor Gajic @ 14.12.2009. 18:28 ] @
Mozes i ovako koriscenjem XML objekta i XSLT-a:
Code:

            XmlDocument doc = new XmlDocument();
            doc.LoadXml("XML doc string.....");

            XmlNodeList nodes = doc.SelectNodes("//OsobaA/Podaci");

            foreach (XmlNode node in nodes)
            {
                Console.WriteLine(node.SelectSingleNode("Godina").InnerText);
            }

            Console.WriteLine(doc.SelectSingleNode("Obrada/DatumPrijave").InnerText);


XML treba da bude validan, dakle XML bi trebalo da izgleda otprilike:

Code:

<?xml version="1.0" encoding="UTF-8"?>
<Obrada xmlns:osobe="urn:OsobaA.xsd">
  <DatumPrijave>
    <Datum>2009-12-11</Datum>
  </DatumPrijave>
  <OsobaA>
    <Podaci>
      <Godina>2009</Godina>
    </Podaci>
  </OsobaA>
  <OsobaA>
    <Podaci>
      <Godina>2007</Godina>
    </Podaci>
  </OsobaA>
  <OsobaB>
    <Podaci>
      <Godina>2001</Godina>
    </Podaci>
  </OsobaB>
</Obrada>
[ malo_nj @ 14.12.2009. 18:29 ] @
moze x puta isti tag al nema u ovom slucaju bas nekog smisla. A za ovo drugo sto ti rekoh moras staviti </OsobaB> a ne </Osobab> inace ce ti prijavljivati gresku
[ Igor Gajic @ 14.12.2009. 18:39 ] @
Citat:

Npr da mi da sve podatke cije ime noda pocinje recimo sa "OSOBA". Da li je ovo moguce?


Moze, recimo ovako:

Code:

            XmlNodeList nodes = doc.SelectNodes("descendant::*");

            foreach (XmlNode node in nodes)
            {
                if(node.Name.StartsWith("Osoba"))
                Console.WriteLine(node.SelectSingleNode("Podaci/Godina").InnerText);
            }
[ mmix @ 15.12.2009. 10:23 ] @
@malo_nj, resenj radi ali je malo obsolete, rucna iteracija preko XML dokumenata u doba xPatha je retko kad potrebna.

@Igor, problem sa resnjem je sto njegov XML dokument ima default namespace i ne moze tako direktno da se isptuje jer SelectSingleNode tretira default namespace isto kao i named. I pride nema potrebe da se radi iteracija za Osoba*, postoji Xpath konstrukcija za to

u globalu kod koji radi posao je:

Code:
XmlDocument doc = new XmlDocument();
doc.LoadXml(" .... ovde ide XML dockument ....");
            
XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("urn", "urn:OsobaA.xsd");

// pod uslovom da postoji samo jedan datum node u xml fajlu, ako ne mora da se scope skrati
string datum = doc.SelectSingleNode("//urn:Datum", mgr).InnerText;     
XmlNodeList osobe = doc.SelectNodes("//*[substring(name(.), 1, 5) = 'Osoba']", mgr);


[ CallMeSaMaster @ 15.12.2009. 11:55 ] @
@MMIX

Moze li se ovaj "xlmns=...." na neki nacin replace sa praznim stringom? Moja zamisao je da proslijedim bilo koji XML i da ga obradjujem. Medjutim shvatio sam da mi se ovaj dio pojavljuje u svakom xml-u, ali se razlikuje od xml-a do xml-a.

Htio bih da ga detektujem, zatim replace sa praznims tringom, i da nastavim obradjivati taj izmjenjeni XML.

Kako mogu to da uradim.

Napomena. XML dobijam kao takve, tako da ne mogu nista uciniti po tom pitanju. U smislu "nemoj pisati to u xml file". Osim naravno da rucno brisem ali mi se ne svidja to.
[ mmix @ 15.12.2009. 12:12 ] @
Ako hoces koser resenje trebalo bi da detektujes default namespace root elementa ucitanog doc-a i da ga ubacis sa svojim prefixom (onim koji koristis u xpath izarazu) u namespace managera.

Npr.
Code:

XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("urn", doc.DocumentElement.NamespaceURI);
string datum = doc.SelectSingleNode("//urn:Datum", mgr).InnerText;

[ CallMeSaMaster @ 15.12.2009. 12:22 ] @
Sorry ne znam da li sam te shvatio.

Htio bih da maknem skorz ovo iz XML-a. Da ga izvorni XML ima u sebi ali prilikom obrade da ga ja ukinem ili ignorisem nekako.

Hvala
[ CallMeSaMaster @ 15.12.2009. 12:26 ] @
AAaaaaaaaaaaaa, mislimd a sam shvatio. U sustini mi je svejedno sta tu pise, samo ga pokupim i setujem managerom. Jesi to htio reci?
Ok, mislim da je to to!
[ CallMeSaMaster @ 15.12.2009. 12:40 ] @
Molim te reci mi samo, sta ko imam tagove npr. DatumObrade i koji se nalazi i u "Obradi" i u "Osobi". Ovdje zanci mislim na dva ista naziva u razlicitim sekcijama. Kako cu pristupiti tim dijelovima?(Vidi primjer ispod)

Hvala jos jendom

Code:

<?xml version="1.0" encoding="UTF-8"?>
<Obrada xmlns:osobe="urn:OsobaA.xsd">
  <DatumPrijave>
    <DatumObrade >2009-12-11</DatumObrade >
  </DatumPrijave>
  <OsobaA>
    <Podaci>
      <DatumObrade >2009-12-11</DatumObrade >
    </Podaci>
  </OsobaA>
  <OsobaA>
    <Podaci>
      <DatumObrade >2009-12-11</DatumObrade >
    </Podaci>
  </OsobaA>
  <OsobaB>
    <Podaci>
      <DatumObrade >2009-12-11</DatumObrade >
    </Podaci>
  </OsobaB>
</Obrada>


[ Igor Gajic @ 15.12.2009. 12:49 ] @
Code:

            XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
            mgr.AddNamespace("urn", doc.DocumentElement.NamespaceURI);

            XmlNodeList nodes = doc.SelectNodes("//child::*[contains(name(.),'Osoba')]",mgr);

            foreach (XmlNode node in nodes)
            {
                Console.WriteLine(node.SelectSingleNode("Podaci/DatumObrade ").InnerText);
            }

            Console.WriteLine(doc.SelectSingleNode("Obrada/DatumPrijave/DatumObrade ", mgr).InnerText);




Najbolje bi bilo da procesljas XPath sintaksu jer 95% problema resavaces sa njim.

Imas tutorijal na:

http://www.w3schools.com/XPath/xpath_nodes.asp
[ mmix @ 15.12.2009. 13:35 ] @
Zapravo xpath

Code:
//*[substring(name(.), 1, 5) = 'Osoba']/urn:Podaci/urn:DatumObrade 


ce vratiti niz nodova sa datumima obrada osoba ako je urn registrovani prefix u menadzeru ako si trazio izvor za neku agregaciju, a ako ti treba drill down unutar noda osobe koju vec imas onda ide node.SelectSingleNode("urn:Podaci/urn:DatumObrade", mgr).InnerText koa sto ti je Igor dao uz napomenu da contains vraca i nodove oblika %Osoba% a ne samo Osoba%, da su prefixi i dalje potrebni u xpath-u u .NET implementaciji, a child axis nije potrebno navoditi jer je implicitan u node path-u.


u ovakvom obliku xmla i datum obrade u datumu prijave zadovoljava inicijalni //urn:DatumPrijave oblik pa moras da iskoristis //urn:DatumPrijave/urn:DatumObrade xpath da bi izvukao samo njega. U principu scope gradis ili od samog roota do elementa koji juris ili relativno u odnosu na neki specificni node ciji format znas.


Citat:
CallMeSaMaster: AAaaaaaaaaaaaa, mislimd a sam shvatio. U sustini mi je svejedno sta tu pise, samo ga pokupim i setujem managerom. Jesi to htio reci?
Ok, mislim da je to to!


Da, pride je cak i nevazno koji prefix koristis u menadzeru moze da bude i

Code:

XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("abc", doc.DocumentElement.NamespaceURI);
string datum = doc.SelectSingleNode("//abc:Datum", mgr).InnerText;


menadzer ce osigurati da se pretraga obavi po odgovarajucem namespace-u.
[ CallMeSaMaster @ 15.12.2009. 14:38 ] @
Ipak nisi me shavtio. Meni je svejedno sta, u XML-u koji dodje, pise kao namespace. Problem mi se javlja kada ja zelim da uzemem OuterXML nekog elementa recimo, "OsobaA". U tom slucaju mi se automatski postavi Namespace koji pise u XMLu koji je dosao. Medjutim ja mogu imati Razlicite osobe, recimo "OsobaB" koja naravno nema isti namespace kao i OsobaA. I tu mi nastaje konflikt. Onda mi u osobu B pise namespace od A koji naravno nije tacan.

Malo da pojasnim. Neki korisnik moze da naprvi XML file u kojem je stavio namespace od OsobeA, ali isto tako da dodaje elemente koji su OsobaB. Meni je bitno da uzmem taj njegov XML i da pokupim nodove sa OuterXML ali bez da mi se automatski doda defaultni namespace XML-a.

Jednostavno zelim ukinuti ovaj namspace gdje god se nalazio u XMl-u. Moze li se to izvesti?
[ Igor Gajic @ 15.12.2009. 15:06 ] @
Cek, jel mozes da das neki kompleksniji primer XML koji zelis da obradis ?

Ja koliko sam te shvatio, ti imas XML koji je oblika:

Code:

<?xml version="1.0" encoding="UTF-8"?>
<osobe:Obrada xmlns:osobe="urn:OsobaA.xsd">
  <DatumPrijave>
    <DatumObrade >2009-12-11</DatumObrade >
  </DatumPrijave>
  <a:OsobaA xmlns:a="urn:OsobaA.dtd">
    <Podaci>
      <DatumObrade >2009-12-11</DatumObrade >
    </Podaci>
  </a:OsobaA>
  <a:OsobaA xmlns:a="urn:OsobaA.dtd">
    <Podaci>
      <DatumObrade >2009-12-11</DatumObrade >
    </Podaci>
  </a:OsobaA>
  <b:OsobaB xmlns:b="urn:OsobaB.xsd">
    <Podaci>
      <DatumObrade >2009-12-11</DatumObrade >
    </Podaci>
  </b:OsobaB>
</osobe:Obrada>


U kojem imas vise razlicitih namespaceova i vise razlicitih osoba. I trebas da pokupis XML BEZ ovih namespaceova i da imas samo nodove OsobaA,OsobaB,OsobaC ?

Ne vidim u cemu je problem sa ovim posto gore navedeni kod uzima nodove OsobaXYZ bez obzira koji je namespace, posto je NamespaceManager pokupio sve namespaceove iz dokumenta.
[ mmix @ 15.12.2009. 19:00 ] @
Citat:
CallMeSaMaster: Jednostavno zelim ukinuti ovaj namspace gdje god se nalazio u XMl-u. Moze li se to izvesti?


Odgovor je i da i ne. Naizgled je lako jer najobiciniji regex search/replace moze iz xmla da 'izbaci' xmlns="...". A razlog zasto to ne treba da radis cu ti dati uz ovaj primer, pogledaj ova dva xml fajla:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<root atribut="vrednost" xmlns="http://www.elitesecurity.org/p2466827/primer">
   <osoba pol="muski"> 
      <ime>pera</ime>
      <prezime/>
   </osoba>
</root>

Code:
<?xml version="1.0" encoding="UTF-8"?>
<mojns:root mojns:atribut="vrednost" xmlns:mojns="http://www.elitesecurity.org/p2466827/primer">
   <mojns:osoba mojns:pol="muski">
      <mojns:ime>pera</mojns:ime>
      <mojns:prezime/>
   </mojns:osoba>
</mojns:root>


Ova dva XMLa su IDENTICNA sa dve razlicite tekstualne reprezentacije. Imaju identican DOM i iste XSLT, XPath i XQuery operacije generisu identicne rezultate, itd, itd. Sto je najgore po tebe, ovih tekstualnih reprezentacija moze da bude beskonacno mnogo jer prefixmoze da bude bilo koji i sta vise moze da ih bude vise koji nose isti URI, npr:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<mojns:root mojns:atribut="vrednost" 
      xmlns:mojns="http://www.elitesecurity.org/p2466827/primer" 
      xmlns:tvojns="http://www.elitesecurity.org/p2466827/primer">
   <mojns:osoba tvojns:pol="muski">
      <mojns:ime>pera</mojns:ime>
      <tvojns:prezime/>
   </mojns:osoba>
</mojns:root>


Ovaj xml je identican kao gornja dva, ima dva prefixa ali oba imaju istu namespaceURI i po definiciji su isti.

Iz ovih razloga bi trebao da izbegavas bilo kakvo modifikovanje XML fajlova kao stringova, sto ukljucuje search/replace, skracivanje, konkatenaciju, itd, itd.. Zato kad pricam o XMLu obicno napomenem da je nesto "kosher" kao resenje koje funkcionise lepo i sa namespaceovima.

E sad, ako su ns1 i ns2 dva prefixa za dva razlicita namespace URIa onda su nodovi ns1:OsobaA i ns2:OsobaA dva potpuno razlicita tipa node-a bez obzira na to sto im je lokalno ime isto i DOM ih tretira kao razlicite tipove, okidaju ih razlicite xpath putanje, itd. i zbog toga ti imas problema jer mislis da su isto a nisu. Kontam da to nije tvojom krivicom jer ti dobijas te fajlove spolja ali feler u ovoj situaciji lezi na ljudima koji generisu xml fajlove koje ti salju jer ih markiraju bezveznim namespacovima. Koncept pretvaranja ns2:OsobaA u ns1:OsobaA je sa stanovista XMLa isti proces kao promena iz ns1:OsobaA u ns2:OsobaB, tj radi se o transformaciji nodova. Postoje dva koser resenja:

1. Primena XSLT transformacije sto je mozda malo overkill za tvoje potrebe
2. Promena Namespace-a za celo DOM stablo, sto se radi iterativno ili rekurzivno kroz klasicni C# kod ili kroz konstrukcije iz LINQ for XML

U oba slucaja generisi XML koji ima tvoj fiksirani namespace (ili ukloni namespace kompletno) i imaces uniformni izlaz.