XML dodawanie węzła w C#

Odpowiedz Nowy wątek
2012-03-07 13:18
problemik
0

Czy ktoś mógłby mi doradzić jak wykonać pewną rzecz?
Mam taki plik XML:

  • <dane> - <kontakty> - <kontakt> <imie>Stefan</imie> <nazwisko>Jakis</nazwisko> </kontakt> - <kontakt> <imie>Jacek</imie> <nazwisko>Golebowski</nazwisko> </kontakt> </kontakty> </dane>

I chciałbym dodawać do tego pliku kolejne węzły, ale w sposób taki, aby nowy węzeł
był w tagach: <kontakt></kontakt>, ale w drzewie <kontakty></kontakty>, a nie w drzewie <dane></dane>

Na razie mam taki kod:

            string filename = "C:\\products.xml";
            XmlDocument doc = new XmlDocument();
            doc.Load(filename);
            XmlNode node = doc.CreateNode(XmlNodeType.EndElement, "Kontakt", null);
            XmlNode nodeTitle = doc.CreateElement("Imie");
            nodeTitle.InnerText = "Bogdan";
            node.AppendChild(nodeTitle);
            doc.DocumentElement.AppendChild(node);
            doc.Save(filename);

Ale niestety węzeł jest dodawany w drzewie <dane></dane>, a nie w drzewie <kontakt></kontakt>.

Pytanie dodatkowe: Czy w pliku XML można przechowywać zbiór różnych niepowiązanych ze sobą informacji?
Np mamy zbiór osoby, gdzie danymi są imię, nazwisko, adres itp
oraz czy do tego samego pliku można dodać osobne drzewo np produkty gdzie dane to nazwa, ilość, cena itp?

Czy do każdego typu (osoby , produkty) trzeba tworzyć osobny plik XML?

Pozostało 580 znaków

2012-03-07 13:40
1

Czy pojawia się w twoim kodzie gdzieś nazwa elementu "Kontakty"? Nie. Skąd więc komputer ma wiedzieć, że chcesz dodawać do „Kontaktów”.

Z kodem tak dokładnie to ci nie pomogę, bo klasy XmlDocument nie ogarniam. Mogę ci podać przykład z użyciem XElement:

    using System.Xml.Linq;
...
    var dane = XElement.Load("products.xml");

    var nowy_kontakt = new XElement("Kontakt",
        new XElement("Imie", "Bogdan"),
        new XElement("Nazwisko", "Szmit"));

    dane.Element("Kontakty").Add(nowy_kontakt);
    dane.Save("products2.xml");

Plik XML może mieć strukturę jaką tylko chcesz, ale musi być jeden element nadrzędny, tzw. root (korzeń drzewa). To zazwyczaj nie jest problem:

<Dane>
    <Kontakty>
        <Kontakt>
            <Imie>Stefan</Imie> 
            <Nazwisko>Jakis</Nazwisko> 
        </Kontakt>
        <Kontakt>
            <Imie>Jacek</Imie> 
            <Nazwisko>Golebowski</Nazwisko> 
        </Kontakt>
    </Kontakty>
    <NiepowiazaneInformacje>
        <Cena>123</Cena>
    </NiepowiazaneInformacje>
</Dane>
edytowany 2x, ostatnio: Azarien, 2012-03-07 13:42

Pozostało 580 znaków

2012-03-07 14:20
problemik
0

Serdecznie dziękuję :)

Pozostało 580 znaków

2012-03-07 16:46
problemik
0

Mam jeszcze mały problem z usuwaniem węzłów.
Przykładowo mam taki plik:

  • <dane> - <kontakty> - <kontakt> <imie>Patryk</imie> <nazwisko>Jakis</nazwisko> <telefon>206-555-0144</telefon> <address>Bydgoszcz</address> </kontakt> - <kontakt> <imie>Mikołaj</imie> <nazwisko>Rej</nazwisko> <telefon>205-000-0224</telefon> <address>Warszawa</address> </kontakt> - <kontakt> <imie>Paweł</imie> <nazwisko>Dusigrosz</nazwisko> <telefon>000-000-0002</telefon> <address>Szczecin</address> </kontakt> </kontakty>
  • <produkty> -<produkt> <nazwa>Cukier</nazwa> <cena>12</cena> </produkt> </produkty>

    </dane>

I chciałbym usunąć sobie wpis:

  • <kontakt> <imie>Paweł</imie> <nazwisko>Dusigrosz</nazwisko> <telefon>000-000-0002</telefon> <address>Szczecin</address> </kontakt>

Na razie doszedłem do czegoś takiego:

            XmlDocument d = new XmlDocument();
            d.Load("C:\\products.xml");
            XmlNode t = d.SelectSingleNode("dane//Kontakty//Kontakt[@imie='Paweł']");
            t.RemoveChild(t);

            d.Save("C:\\products.xml");

Niestety to wywala błąd

Doszedłem też do tego:

            XElement allData = XElement.Load("C:\\products.xml");
            XElement child3 = allData.Element("Kontakty");
            child3.Remove();

            allData.Save("C:\\products.xml");

I tu usuwa, ale całe Kontakty, a nie tylko jeden wpis. Wiem, że to normalne bo to wynika z kodu, ale nie wiem jak zmusić program do usunięcia konkretnego rekordu w tej linijce:
XElement child3 = allData.Element("Kontakty");

Byłbym wdzięczny za podanie sposobu na usunięcie danego wpisu.

Pozostało 580 znaków

2012-03-07 17:06
ŁF
0
problemik napisał(a)

Na razie doszedłem do czegoś takiego:


XmlDocument d = new XmlDocument();
d.Load("C:\\products.xml");
XmlNode t = d.SelectSingleNode("dane//Kontakty//Kontakt[@imie='Paweł']");
t.RemoveChild(t);
        d.Save("C:\\products.xml");
> Niestety to wywala błąd

<span style='font-size:24px'>JAKI BŁĄD???</span> rzucany wyjątek zawiera pełną treść błędu, jeśli jej nie czytasz, to jesteś idiotą. to tak, jakbyś przywiózł do mechanika samochód, a na pytanie co jest nie tak odpowiedział: "nie działa". nieważne, że masz na myśli prawe światło stopu.

jeśli istnieje co najmniej jeden element i chcesz usunąć pierwszy:
```csharp
allData.Element("Kontakty").Elements("Kontakt").Single(e => e.Element("Imie").Value == "Paweł").Remove();

jeśli nie wiesz, ile jest elementów, a chcesz usunąć każdy; nie jestem pewien, czy to zadziała, bo nie chce mi się tego kompilować bo wewnątrz foreach jest modyfikowana lista, po której biega foreach:

allData.Element("Kontakty").Elements("Kontakt").Where(e => e.Element("Imie").Value == "Paweł").ToList().ForEach(e => e.Remove());

tu wersja, która na pewno zadziała:

try { 
  var a = allData.Element("Kontakty").Elements("Kontakt").Where(e => e.Element("Imie").Value == "Paweł").ToArray();
  for (int i=0; i < a.Length; a[i++].Remove());
} catch { }

edytowany 5x, ostatnio: ŁF, 2012-03-07 17:13

Pozostało 580 znaków

2012-03-07 17:19
problemik
0

Najmocniej dziękuję.
Wszystko działa jak należy :)

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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