Entwickler-Ecke

IO, XML und Registry - TreeView und XML


bambam77 - Do 10.09.09 09:56
Titel: TreeView und XML
Hallo

Seit paar Tagen beschäftige ich mich mit C#. Ich muss eine kleine winform-Applikationb mit TreeView erstellen. Als Quelle für TreeVie nutze ich folgendes XML Dokument (hier nur ein Abschnitt):


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
<?xml version="1.0" encoding="utf-8" ?>
<storage>
  <documents>
    <doc id="" prod="Product A" name="Product A - Manual1" ... file="Product-A-Manual1.pdf" />
    <doc id="" prod="Product A" name="Product A - Manual2" ... file="Product-A-Manual2.pdf" />
    <doc id="" prod="Product A" name="Product A - Manual3" ... file="Product-A-Manual3.pdf" />
    <doc id="" prod="Product A" name="Product A - Manual4" ... file="Product-A-Manual4.pdf" />
    <doc id="" prod="Product B" name="Product B - Manual1" ... file="Product-B-Manual1.pdf" />
    <doc id="" prod="Product B" name="Product B - Manual2" ... file="Product-B-Manual2.pdf" />
    <doc id="" prod="Product B" name="Product B - Manual3" ... file="Product-B-Manual3.pdf" />
    <doc id="" prod="Product B" name="Product B - Manual4" ... file="Product-B-Manual4.pdf" />
    <doc id="" prod="Product C" name="Product C - Manual1" ... file="Product-C-Manual1.pdf" /> 
    <doc id="" prod="Product C" name="Product C - Manual2" ... file="Product-C-Manual2.pdf" />
    <doc id="" prod="Product D" name="Product D - Manual1" ... file="Product-D-Manual1.pdf" />
    <doc id="" prod="Product E" name="Product E - Manual1" ... file="Product-E-Manual1.pdf" />
    <doc id="" prod="Product F" name="Product F - Manual1" ... file="Product-F-Manual1.pdf" />
    <doc id="" prod="Product F" name="Product F - Manual2" ... file="Product-F-Manual2.pdf" />
  </documents>
 </storage>


Ich habe leider kein Einfluss auf die Struktur...

Ich eine ein Problem mit den Produkten (<doc ... prod="..."/>). Wie man es oben sehen kann, für einen Produkt können mehree Dokumente vorhanden werden.
Und genau das gleiche sehe ich im TreeView:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
- Produkt A
-- doc1
-- doc2
-- doc3
- Produkt A
-- doc1
-- doc2
-- doc3
- Produkt A
-- doc1
-- doc2
-- doc3
- Produkt A
-- doc1
-- doc2
-- doc3
- Produkt B
-- doc4
-- doc5
-- doc6
- Produkt B
-- doc4
-- doc5
-- doc6
- Produkt B
-- doc4
-- doc5
-- doc6
- Produkt B
-- doc4
-- doc5
-- doc6


Das aber entspricht meinem Plan nicht :)

Und mein Plan sieht so aus:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
- Produkt A
-- doc1
-- doc2
-- doc3
- Produkt B
-- doc4
-- doc5
-- doc6


Wie kann ich es erreichen?

Anbei mein Code fürs TreeView:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
private void populateTreeView()
        {
            try
            {
                TreeNode t1, t2;
                if (xmlFile != null && xmlTree != null)
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(xmlFile);
                    XmlNodeList nodeList = doc.SelectNodes("storage/products/doc");
                    foreach (XmlNode node in nodeList)
                    {

                        t1 = new TreeNode(node.Attributes["prod"].Value); 
                        string prodName = node.Attributes["prod"].InnerText; 
                        xmlTree.Nodes.Add(t1);
                        foreach (XmlNode nod in node.SelectNodes("//doc[@prod=" + '"' + prodName + '"' + "]"))
                        {
                            t2 = new TreeNode(nod.Attributes["file"].Value);
                            t1.Nodes.Add(t2);
                        }

                    }
                }
            }
            catch(Exception exp)
            {
                MessageBox.Show(exp.Message);
            }
        }


Kann mir jemand ein Tipp geben, wie kann ich es lösen?

Danke in Voraus
bb

Moderiert von user profile iconChristian S.: Code- durch XML- und C#-Tags ersetzt


bambam77 - Do 10.09.09 13:08

Da ich gerade es nicht auprobieren kann, kann mir jemand sagen, ob ich richtig denke:


Quelltext
1:
2:
3:
4:
5:
 t1 = new TreeNode(node.Attributes["prod"].Value); 
 string prodName = node.Attributes["prod"].InnerText; 
 
 if (t1 != node.previousSibling("@prod=" + t1 + ")) //etwas wie das hier...
 xmlTree.Nodes.Add(t1);


natürlich Kode ist kann syntaktisch nicht ganz korrekt sein, es geht mir nur um die Idee :)


danke
bb


Kha - Do 10.09.09 17:45

:welcome:

Die Logik stimmt, ich würde aber nicht über die TreeNode-Variable gehen:

C#-Quelltext
1:
2:
if (node.PreviousSibling != null && node.PreviousSibling.Attributes["prod"].Value == node.Attributes["prod"].Value)
  continue;


bambam77 - So 13.09.09 08:35

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
:welcome:

Die Logik stimmt, ich würde aber nicht über die TreeNode-Variable gehen:

C#-Quelltext
1:
2:
if (node.PreviousSibling != null && node.PreviousSibling.Attributes["prod"].Value == node.Attributes["prod"].Value)
  continue;


Danke Kha, es hat mir weitergeholfen :)

Ich habe es weitergenutzt um die Dateien (files) bei jedem Produkt in Gruppen zu gliedern:


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
<documents>
<doc id="" prod="Product A" ... gr="A"       file="Product-A-Manual.pdf" />
<doc id="" prod="Product A" ... gr="A"       file="Product-A-Manual1.pdf" />
<doc id="" prod="Product A" ... gr="Install Drivers"   file="Product-A-Stuerung-Treiber-Install.msi" />
<doc id="" prod="Product A" ... gr="Execute Drivers"   file="Product-A-Stuerung-Treiber-Execute.zip" />
<doc id="" prod="Product A" ... gr="Execute Drivers"   file="Product-A-Stuerung-Treiber-Execute.zip" />
<doc id="" prod="Product B" ... gr="B"       file="Product-B-Manual2.pdf" />
<doc id="" prod="Product B" ... gr="B"       file="Product-B-Manual.pdf" />
<doc id="" prod="Product B" ... gr="B"       file="Product-B-Manual1.pdf" />
<doc id="" prod="Product B" ... gr="Install Drivers"   file="Product-B-Stuerung-Treiber-Install.msi" />
<doc id="" prod="Product B" ... gr="Execute Drivers"   file="Product-B-Stuerung-Treiber-Execute.zip" />
<doc id="" prod="Product C" ... gr="Execute Drivers"   file="Product-C-Stuerung-Treiber-Execute.zip" />
<doc id="" prod="Product C" ... gr="Install Drivers"   file="Product-C-Stuerung-Install-Treiber.zip" />
<doc id="" prod="Product D" ... gr="A"       file="Product-D-Manual.pdf" />
<doc id="" prod="Product D" ... gr="B"       file="Product-D-Manual1.pdf" />
<doc id="" prod="Product E" ... gr="Install Drivers"   file="Product-E-Stuerung-Treiber-Install.msi" />
</documents>



C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
foreach (XmlNode nodeProd in nodeList)
{
   t1 = new TreeNode(nodeProd.Attributes["prod"].Value);
   string prodName = nodeProd.Attributes["prod"].InnerText; 
                        
   if (nodeProd.PreviousSibling == null)
      xmlTree.Nodes.Add(t1);
   if (nodeProd.PreviousSibling != null && nodeProd.PreviousSibling.Attributes["prod"].Value != nodeProd.Attributes["prod"].Value)                
      xmlTree.Nodes.Add(t1);
                        
      foreach (XmlNode nodeGroup in doc.SelectNodes("storage/documents/doc[@prod=" + '"' + prodName + '"' + "]"))
      {
         t2 = new TreeNode(nodeGroup.Attributes["gr"].Value);
         string grName = nodeGroup.Attributes["gr"].InnerText;                          

         if (nodeGroup.PreviousSibling == null)
            t1.Nodes.Add(t2);
         if (nodeGroup.PreviousSibling != null && nodeGroup.PreviousSibling.Attributes["gr"].Value != nodeGroup.Attributes["gr"].Value)
            t1.Nodes.Add(t2);

            foreach (XmlNode nodeDoc in doc.SelectNodes("//doc[@gr=" + '"' + grName + '"' + "][@prod=" + '"' + prodName + '"' + "]"))
            {
               t3 = new TreeNode(nodeDoc.Attributes["file"].Value);                                        
               t2.Nodes.Add(t3);
            }
       }


Es funktioniert soweit, aber ich habe ein Problem, nämlich, wenn im "Produkt B" die letzte und im "Produkt C" die erste Gruppe "Execute Drivers" ist, wird es bei dem Produkt C nicht angezeigt.

Ich habe gedacht, dass ich dem Spielraum schon mit dem "nodeGroup" nur an die jeweilige Produkte begrenzt habe, aber es sieht nicht so aus.

Kann mir jemand noch einen Tipp geben?
Danke :)


Kha - So 13.09.09 10:08

Du musst die Bedingung in der inneren Schleife wiederholen:

C#-Quelltext
1:
if (nodeGroup.PreviousSibling != null && (nodeGroup.PreviousSibling.Attributes["gr"].Value != grName || nodeGroup.PreviousSibling.Attributes["prod"].Value != prodName))                    

Wenn ich das richtig sehe, müsstest du allerdings viele doppelte Einträge erhalten, da du die Schleife nicht verlässt, wenn die Bedingung nicht zutrifft (s. mein continue).


bambam77 - So 13.09.09 14:44

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Du musst die Bedingung in der inneren Schleife wiederholen:

C#-Quelltext
1:
if (nodeGroup.PreviousSibling != null && (nodeGroup.PreviousSibling.Attributes["gr"].Value != grName || nodeGroup.PreviousSibling.Attributes["prod"].Value != prodName))                    

Wenn ich das richtig sehe, müsstest du allerdings viele doppelte Einträge erhalten, da du die Schleife nicht verlässt, wenn die Bedingung nicht zutrifft (s. mein continue).


Danke, jetzt sehe ich, wie wenig ich weiss... :)

Ich habe Dein Cod genutzt und es funktioniert. Ich kriege auch keine doppelte Einträge (vielleicht liegt es an dem doc.SelectNodes bei nodeGroup), ausser eine Ausnahme, wenn XML wie folgend aufgebaut ist:


XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
<documents>
<doc id="" prod="Product A" ... gr="A"       file="Product-A-Manual.pdf" />
<doc id="" prod="Product A" ... gr="A"       file="Product-A-Manual1.pdf" />
<doc id="" prod="Product A" ... gr="Install Drivers"   file="Product-A-Stuerung-Treiber-Install.msi" />
<doc id="" prod="Product A" ... gr="Execute Drivers"   file="Product-A-Stuerung-Treiber-Execute.zip" />
<doc id="" prod="Product A" ... gr="Execute Drivers"   file="Product-A-Stuerung-Treiber-Execute.zip" />
<doc id="" prod="Product A" ... gr="A"       file="Product-A-Manual2.pdf" />
<doc id="" prod="Product B" ... gr="B"       file="Product-B-Manual2.pdf" />
...


Leider mit precvioussibling kann man nur die unmittelbar vorausgehende Knoten prüfen. Ich habe bis jetzt darüf keine Lösung gefunden.

Danke und Grüsse