Wybieranie węzłów pliku XML przez XPATH

0

Mam problem z zaczęciem odczytywania z mojego pliku XML przez XPATH w metodach SelectNode() i SelectNodes().

Robie próby na takim kodzie:

XmlDocument doc = new XmlDocument();
doc.Load(@"C:\xml4w1.xml");

XmlNodeList wezlyZamowieniaZO = doc.SelectNodes("/session/DokumentHandlowy");
 

Pytania XPATH buduje wg tutoriali jakie znalazłem w necie ale poza wyrażeniem "/" które zwraca mi węzel session i wyrażeniem "//" które zwraca mi wszystkie węzły i podwęzły z dokumentu w jednym poziomie nic mi nie wychodzi.

Nie wiem dlaczego nie działają mi wyrażenia np. "/session/Towar", "/session//Towar", "Towar" lub "/session/DokumentHandlowy/" one zwracają mi pusty (0 elementów) wynik metody SelectNodes() a spodzieam się odpowiednio wszystkich wezłów Towar lub wszystkich DokumentowHandlowych.
Domyslam się ze jest tu jakis haczyk ale nie widze go.

Przeglądałem m.in. tutoriale:
http://codeguru.geekclub.pl/baza-wiedzy/xpath-czyli-kto-pyta-nie-bladzi,2054 - tu jest dzialajacy program w ktorym widac od razu efekty budowanych zapytan
http://www.codeproject.com/Articles/9494/Manipulate-XML-data-with-XPath-and-XmlDocument-C
Ale tam przykłady działają. Mój plik jest jakiś inny.

Format pliku XML na ktorym pracuje przesylam ponizej, z zastrzezeniem ze ponizej w pliku jest jednozamowienie a w jednym pliku XML moze być również wiele zamowień wtedy powielona jest cześć z wezla session, najpierw sa wezly Towarów ktore wystepuja w zamowieniu, potem wezel Kontrahenta a na koncu Zamowienia.

 
<?xml version="1.0" encoding="Unicode"?>
 <session xmlns="http://www.namespace.z.systemu.erp/staly.dla.wszystkich.dokumentow" business="true">
  <Towar business="false" id="id0" key="Kod=Index-ERP-1" guid="5c8cc4b9-01dc-4531-84a7-cf4ac05c4570">
   <Kod>Index-ERP-1</Kod>
   <Nazwa>Nazwa systemowa dla wyrobu o indexie 1</Nazwa>
   <Opis>Dodatkowy opis/systemowy/wyrobu/1</Opis></Towar>
  <Towar business="false" id="id1" key="Kod=Index-ERP-3" guid="abd2423d-bfec-4ab1-889e-b34fee6b345e">
   <Kod>Index-ERP-3</Kod>
   <Nazwa>Nazwa systemowa dla wyrobu o indexie 2</Nazwa>
   <Opis>Dodatkowy opis/systemowy/wyrobu/2</Opis></Towar>
  <Towar business="false" id="id2" key="Kod=Index-ERP-2" guid="ba6d48af-b65c-4612-a8b5-11786619f156">
   <Kod>Index-ERP-2</Kod>
   <Nazwa>Nazwa systemowa dla wyrobu o indexie 3</Nazwa>
   <Opis />
  </Towar>
  <Kontrahent business="false" id="id3" key="Kod=Index-odbiorcy" guid="eb95359d-cafb-425c-a957-5b0510430fad">
   <Kod>Index-odbiorcy</Kod>
   <Nazwa>"Nazwa firmy odbiorcy" sp.j.</Nazwa>
  </Kontrahent>
  <DokumentHandlowy guid="c4bdc359-65da-4e8c-92b9-1491565f1209"><Definicja where="Symbol=ZO" />
   <Data>2014-10-07</Data>
   <Numer>ZO/000521/14</Numer>
   <Kontrahent>id3</Kontrahent>
   <Platnosci />
   <Pozycje>
    <Pozycja>
     <Towar where="Kod=Index-ERP-1" />
     <Ilosc>10 szt</Ilosc>
     <Cena>6.00 PLN</Cena>
    </Pozycja>
    <Pozycja>
     <Towar where="Kod=Index-ERP-3" />
     <Ilosc>10 szt</Ilosc>
     <Cena>6.00 PLN</Cena>
    </Pozycja>
    <Pozycja>
     <Towar where="Kod=Index-ERP-2" />
     <Ilosc>10 szt</Ilosc>
     <Cena>7.00 PLN</Cena>
     </Pozycja>
    <Pozycja>
     <Towar where="Kod=Index-ERP-1" />
     <Ilosc>1 szt</Ilosc>
     <Cena>6.00 PLN</Cena>
    </Pozycja>
    <Pozycja>
     <Towar where="Kod=Index-ERP-3" />
     <Ilosc>1 szt</Ilosc>
     <Cena>6.00 PLN</Cena>
    </Pozycja>
    <Pozycja>
     <Towar where="Kod=Kod=Index-ERP-2" />
     <Ilosc>1 szt</Ilosc>
     <Cena>7.00 PLN</Cena>
    </Pozycja>
    </Pozycje>
  </DokumentHandlowy>
 </session> 
1
XmlDocument doc = new XmlDocument();
doc.Load(@"C:\xml4w1.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("staly.dla.wszystkich.dokumentow", "http://www.namespace.z.systemu.erp/staly.dla.wszystkich.dokumentow");
var root = doc.DocumentElement;
if (root != null)
{
   XmlNodeList towary = root.SelectNodes("staly.dla.wszystkich.dokumentow:Towar", nsmgr);
   XmlNodeList dokumentyHandlowe = root.SelectNodes("staly.dla.wszystkich.dokumentow:DokumentHandlowy", nsmgr);
}

Alternatywa:

XDocument xDoc = XDocument.Load("C:\xml4w1.xml");
string name = @"{http://www.namespace.z.systemu.erp/staly.dla.wszystkich.dokumentow}";
IEnumerable<XElement> towary = xDoc.Root.Elements(name + "Towar");
IEnumerable<XElement> dokumentyHandlowe = xDoc.Root.Elements(name + "DokumentHandlowy");
0

Przestawiłem się jednak całkowicie na klasę XDocument i XElement, są jednak dużo wygodniejsze.
Potrzebuję jeszcze dowiedzieć się jak w tych klasach sprawdzać czy dany węzeł istnieje w dokumencie/elemencie.

Mam taką sytuację, że w dokumencie którego przykład wkleiłem w pierwszym poście, mam wezeł Towar który zawiera wezły** Kod, Nazwa i Opis** ale dla jakiś paru losowych materiałów/towarow system nie eksportuje do pliku XML wezła Opis i próba odczytania jego wartości w taki sposób:

string indexPozycji = pozycja.Element(name + "Towar").Attribute("where").Value;
XElement xTowar = towary.Single(x => x.Attribute("key").Value == indexPozycji);
pozycjaZO.NazwaSprzedazowa = xTowar.Element(name + "Opis").Value;
 

kończy się błędem "Odwołania do obiektu który nie istnieje" w 3 linijce.

Pytanie:
1) Jak w klasie XElement sprawdzać przed odwołaniem się do jakiegoś węzła czy on na pewno istnieje?

1
XElement element = xTowar.Element(name + "Opis");
if (element != null) pozycjaZO.NazwaSprzedazowa = element.Value;

1 użytkowników online, w tym zalogowanych: 0, gości: 1