Autor Beitrag
stoperror
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Do 02.07.09 15:59 
Hallo zusammen,

ich schlage mich gerade mit einem XML-Parser herum.

Ich muss ein XML parsen, das so aussieht:

ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
  <OneTopic>

    <Topic>
      <SubTopics>
        <Topic oder weitere SubTopics...
            </SubTopics>
                <Text Plaintext="TopicTitle"></Text>   
                </Topic>




Ich verwende den XmlTextReader, weil die Dateien groß werden können...
Und möchte aber vom Element Topic auf das Attribut Plaintext zugreifen, ohne im Parser Tags zu überspringen.
Ich habe schon diverse Möglichkeiten, mit XPath und Co ausprobiert, bin aber noch auf keinen grünen Zweig gekommen...
Reader.Readtofollowing war auch nicht das richtige, weil er dan Tags auslässt...

ausblenden volle Höhe 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:
31:
32:
33:
34:
35:
36:
37:
                XmlTextReader reader = new XmlTextReader(this.Importfiletextbox.Text);
                while (reader.Read()) 
                { 
                    switch (reader.NodeType) 
                    { 
                        
                        case XmlNodeType.Element:

                            switch (reader.Name.ToString())
                            {
                                case "OneTopic":
                                    //write header
                                    outputbuffer.Write(createheader());
                                    break;
                                case "Topic":
                                    //write topic
                                    outputbuffer.Write(createtopic(uid));
                                    //write records to buffers

                                    //komm ich vom Topic an das Tag <ap:Text und dessen Attribut plaintext?
                                    /*reader.ReadToFollowing("ap:Text");
                                    list.Add((string)(uid.ToString() + "|" + reader.GetAttribute("PlainText")));*/


                                    uid = uid + 1;
                                    

                                    break;
                                case "SubTopics":
                                    outputbuffer.Write(createsubtopics());
                                    break;
                                case "Text":
                                    outputbuffer.Write(createtitle(reader.GetAttribute("PlainText")));
                                    outputbuffer.Write("</node>\r\n");
                                    break;


....


Bin für jede Hilfe dankbar!
Dankeschön!

Moderiert von user profile iconChristian S.: XML-Tags hinzugefügt
Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 03.07.09 13:30 
:welcome:

user profile iconstoperror hat folgendes geschrieben Zum zitierten Posting springen:
Und möchte aber vom Element Topic auf das Attribut Plaintext zugreifen, ohne im Parser Tags zu überspringen.
Das geht nicht, denn genau daraus zieht der XmlReader schließlich seine Geschwindigkeit:
Zitat:
Represents a reader that provides fast, non-cached, forward-only access to XML data.

Damit du dem Topic seinen Titel zuordnen kannst, bieten sich rekursive Methoden zum Einlesen an, also für jedes Element eine Methode. XmlReader.ReadSubtree dürfte dabei nützlich sein, aber für Genaueres müsstest du erstmal erläutern, welcher Output erwartet wird. Auch die Xml-Struktur ist bei deinem Beispiel nicht ganz klar.

_________________
>λ=
stoperror Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Fr 03.07.09 14:39 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
:welcome:

user profile iconstoperror hat folgendes geschrieben Zum zitierten Posting springen:
Und möchte aber vom Element Topic auf das Attribut Plaintext zugreifen, ohne im Parser Tags zu überspringen.
Das geht nicht, denn genau daraus zieht der XmlReader schließlich seine Geschwindigkeit:
Zitat:
Represents a reader that provides fast, non-cached, forward-only access to XML data.



Damit du dem Topic seinen Titel zuordnen kannst, bieten sich rekursive Methoden zum Einlesen an, also für jedes Element eine Methode. XmlReader.ReadSubtree dürfte dabei nützlich sein, aber für Genaueres müsstest du erstmal erläutern, welcher Output erwartet wird. Auch die Xml-Struktur ist bei deinem Beispiel nicht ganz klar.


Erstmal danke für die Antwort.
ich versuch das ganze im Anschluss noch mal klarer zu beschreiben.

Input z. B.:
OneTopic ist das Wurzelelement, es enthält das Haupttopic 1 (hier Home)
Und dieses Haupttopic kann wiederum Suptopics enthalten. Diese Subtopics können wieder aus Topics und Subtopics bestehen in beliebiger Tiefe...

Also hier:

Home
- Unternehmen
- Leistungen
-- Leistung A
--- Leistung A1
-- Leistung B


ausblenden volle Höhe XML-Daten
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:
33:
34:
      <OneTopic>
        <Topic>
          <SubTopics>
            <Topic>
                                                 <Text PlainText="Unternehmen">
                   </Text>
                                                </Topic>
            <Topic>
                                                 <SubTopics>
               <Topic>
                                                    <SubTopics>
                                                       <Topic>
                                                         <Text PlainText="Leistung A1">
                         </Text>
                                                       </Topic>
                                                    </SubTopics
                                                    <Text PlainText="Leistung A">
                      </Text>
                                                   </Topic>
                                                  
               <Topic>
                                                    <Text PlainText="Leistung B">
                      </Text>
                                                   </Topic>                                                 </SubTopics>
                                                 <Text PlainText="Leistungen">
                   </Text>

                                                </Topic>  
          
          </SubTopics>
          <Text PlainText="HOME">
          </Text>
        </Topic>
      </OneTopic>




Der Output soll t3d (Typo 3-xml) werden, wobei ich die obige Struktur mehrfach abbilden muss:

T3D-Header... (schreib ich einfach so raus)
<T3RecordDocument>
ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
  <header type="array">
    <charset>iso-8859-1</charset>
    <XMLversion>1.0</XMLversion>
    <meta type="array">
                </meta>
    <static_tables index="relStaticTables" type="array">
      <tablename index="0">_ALL</tablename>
    </static_tables>
    <excludeMap type="array">
    </excludeMap>
    <softrefCfg type="array">
    </softrefCfg>
    <extensionDependencies type="array">
    </extensionDependencies>

T3D header pagetree mit den ids, die ich beim parsen generieren muss (uids):

ausblenden XML-Daten
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:
    <pagetree type="array">
      <node index="0" type="array">
        <uid>0</uid>
        <node index="subrow" type="array">
          <node index="37" type="array">
            <uid>37</uid>
            <node index="subrow" type="array">
              <node index="39" type="array">
                <uid>39</uid>
              </node>
              <node index="47" type="array">
                <uid>47</uid>
              </node>
              <node index="45" type="array">
                <uid>45</uid>
              </node>
              <node index="43" type="array">
                <uid>43</uid>
              </node>
              <node index="41" type="array">
                <uid>41</uid>
              </node>
            </node>
          </node>
        </node>
      </node>
    </pagetree>

Das funktioniert auch schon mal soweit.

header records: da muss ich die von mir generierte uid und den Topicnamen irgendwie zusammenkriegen -> und da liegt mein Problem:


ausblenden XML-Daten
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:
    <records type="array">
      <table index="pages" type="array">
        <rec index="uid-Home" type="array">
          <uid>uid-Home</uid>
          <pid>uid-Home</pid>
          <title>Home</title>
          <size>1687</size>
          <relations index="rels" type="array">
          </relations>
          <softrefs type="array">
          </softrefs>
        </rec>
        <rec index="uid-Leistung" type="array">
          <uid>uid-Leistung</uid>
          <pid>uid-Leistung</pid>
          <title>Leistung</title>
          <size>1692</size>
          <relations index="rels" type="array">
          </relations>
          <softrefs type="array">
          </softrefs>
        </rec>
                               ....
                           </table>
                        </records>
                     </header>


Und dann muss ich im Body nochmal so eine Liste mit uid und Title generieren

ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
  <records type="array">
    <tablerow index="pages:uid-Home" type="array">
      <fieldlist index="data" type="array">
        <field index="uid">uid-Home</field>
        <field index="pid">uid-Home</field>
        <field index="title">Home</field>
      </fieldlist>
      <related index="rels" type="array">
      </related>
    </tablerow>      
    <tablerow index="pages:uid-Leistung" type="array">
      <fieldlist index="data" type="array">
        <field index="uid">uid-Leistung</field>
        <field index="pid">uid-Leistung</field>
        <field index="title">Leistung</field>
      </fieldlist>
      <related index="rels" type="array">
      </related>
    </tablerow>  
               ...
         </records>
 </T3RecordDocument>

ich hoffe das macht die Sache nun klarer...
Das gesamte <pagetree> kann ich problemlos mit meiner Lösung nachbauen, würde aber im selben Rutsch auch gerne die beiden anderen Strukturen (records) gleich mit erstellen in einen Stringbuffer schreiben und anschliessend in die Datei schreiben.
Bei meiner Lösung krieg ich aber nicht raus, welche uid zu welchem Topictitle gehört....

Moderiert von user profile iconKha: XML-Tags hinzugefügt

WEnn ich subtree verwende:

while (reader.Read())
{
switch (reader.NodeType)
{

case XmlNodeType.Element:

switch (reader.Name.ToString())
{
case "ap:OneTopic":
//write header
outputbuffer.Write(createheader());
break;
case "ap:Topic":
//write topic
outputbuffer.Write(createtopic(uid));
//write records to buffers

XmlReader test = reader.ReadSubtree();


dann ist mein SubtreeReader übrigens leer.. [System.Xml.XmlSubtreeReader] {None} System.Xml.XmlSubtreeReader