Browse Source

XML Parser hinzugefügt

kolja 5 years ago
parent
commit
1752279af1
10 changed files with 1005 additions and 3 deletions
  1. 1 1
      Bildschirm.cpp
  2. 2 0
      Framework Linux.vcxproj
  3. 6 0
      Framework Linux.vcxproj.filters
  4. 2 0
      Framework.vcxproj
  5. 6 0
      Framework.vcxproj.filters
  6. 2 0
      JSON.cpp
  7. 63 2
      Text.cpp
  8. 16 0
      Text.h
  9. 724 0
      XML.cpp
  10. 183 0
      XML.h

+ 1 - 1
Bildschirm.cpp

@@ -985,7 +985,6 @@ void Bildschirm3D::render() // Zeichnet das Bild
             if( renderOnTop && onTop )
                 onTop->render( *renderB );
         }
-        unlock();
         // Beginne Bild 
         HRESULT result;
 
@@ -999,6 +998,7 @@ void Bildschirm3D::render() // Zeichnet das Bild
         renderObj->setKameraMatrix( view, view.projektion( DirectX::XM_PI / 4.0f, screenAspect, 0.1f, 10000.f ), Vec3< float >( 0.f, 0.f, backBufferSize.y * 1.2075f ) );
         if( fenster && !IsIconic( fenster->getFensterHandle() ) )
             texturModel->render( renderObj );
+        unlock();
 
         result = d3d11SpawChain->Present( 0, 0 );
         renderZeit->messungEnde();

+ 2 - 0
Framework Linux.vcxproj

@@ -150,6 +150,7 @@
     <ClCompile Include="ToolTip.cpp" />
     <ClCompile Include="Welt2D.cpp" />
     <ClCompile Include="Welt3D.cpp" />
+    <ClCompile Include="XML.cpp" />
     <ClCompile Include="Zeichnung.cpp" />
     <ClCompile Include="Zeichnung3D.cpp" />
     <ClCompile Include="Zeit.cpp" />
@@ -216,6 +217,7 @@
     <ClInclude Include="Vec3.h" />
     <ClInclude Include="Welt2D.h" />
     <ClInclude Include="Welt3D.h" />
+    <ClInclude Include="XML.h" />
     <ClInclude Include="Zeichnung.h" />
     <ClInclude Include="Zeichnung3D.h" />
     <ClInclude Include="Zeit.h" />

+ 6 - 0
Framework Linux.vcxproj.filters

@@ -264,6 +264,9 @@
     <ClInclude Include="JSON.h">
       <Filter>Headerdateien\Framework</Filter>
     </ClInclude>
+    <ClInclude Include="XML.h">
+      <Filter>Headerdateien\Framework</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Prozess.cpp">
@@ -419,5 +422,8 @@
     <ClCompile Include="JSON.cpp">
       <Filter>Quelldateien\Framework</Filter>
     </ClCompile>
+    <ClCompile Include="XML.cpp">
+      <Filter>Quelldateien\Framework</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 2 - 0
Framework.vcxproj

@@ -250,6 +250,7 @@ copy "x64\Release\Framework.dll" "..\..\Spiele Platform\SMP\Fertig\x64\framework
     <ClInclude Include="Ebene3D.h" />
     <ClInclude Include="Welt2D.h" />
     <ClInclude Include="Welt3D.h" />
+    <ClInclude Include="XML.h" />
     <ClInclude Include="Zeichnung.h" />
     <ClInclude Include="Prozess.h" />
     <ClInclude Include="Punkt.h" />
@@ -313,6 +314,7 @@ copy "x64\Release\Framework.dll" "..\..\Spiele Platform\SMP\Fertig\x64\framework
     <ClCompile Include="TexturModel.cpp" />
     <ClCompile Include="Welt2D.cpp" />
     <ClCompile Include="Welt3D.cpp" />
+    <ClCompile Include="XML.cpp" />
     <ClCompile Include="Zeichnung3D.cpp" />
     <ClCompile Include="Zeichnung.cpp" />
     <ClCompile Include="Prozess.cpp" />

+ 6 - 0
Framework.vcxproj.filters

@@ -291,6 +291,9 @@
     <ClInclude Include="Dialog.h">
       <Filter>Headerdateien\Framework</Filter>
     </ClInclude>
+    <ClInclude Include="XML.h">
+      <Filter>Headerdateien\Framework</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Maus.cpp">
@@ -467,5 +470,8 @@
     <ClCompile Include="Dialog.cpp">
       <Filter>Quelldateien\Framework</Filter>
     </ClCompile>
+    <ClCompile Include="XML.cpp">
+      <Filter>Quelldateien\Framework</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 2 - 0
JSON.cpp

@@ -364,6 +364,8 @@ Text Parser::removeWhitespace( const char *str )
         case '\n':
         case '\t':
         case '\r':
+            if( strO )
+                ret.getText()[ index++ ] = str[ i ];
             esc = 0;
             break;
         default:

+ 63 - 2
Text.cpp

@@ -87,7 +87,7 @@ void Text::toUpperCase()
     for( int i = 0; txt[ i ]; i++ )
     {
         if( txt[ i ] >= 'a' && txt[ i ] <= 'z' )
-            txt[ i ] -= 32;
+            txt[ i ] -= (char)32;
         switch( txt[ i ] )
         {
         case 'ü':
@@ -110,7 +110,7 @@ void Text::toLowerCase()
     for( int i = 0; txt[ i ]; i++ )
     {
         if( txt[ i ] >= 'A' && txt[ i ] <= 'Z' )
-            txt[ i ] += 32;
+            txt[ i ] += (char)32;
         switch( txt[ i ] )
         {
         case 'Ü':
@@ -505,6 +505,8 @@ void Text::remove( int p ) // l
 
 void Text::remove( int p1, int p2 ) // löscht von p1 zu p2 ( p2 bleibt )
 {
+    if( p1 == p2 )
+        return;
     if( p1 > p2 ) // p1 und p2 tauschen
     {
         int x = p1;
@@ -652,6 +654,36 @@ void Text::remove( int i, Text *t )
     t = t->release(); // Übergabe loslassen
 }
 
+// Löscht alle ' ', '\n', '\r', '\t' bis zu einem anderen buchstaben
+//  pos: Die Position des ersten zeichens
+void Text::removeWhitespaceAfter( int pos )
+{
+    int length = 0;
+    for( int i = pos; i < txt[ i ]; i++ )
+    {
+        if( txt[ i ] == ' ' || txt[ i ] == '\n' || txt[ i ] == '\r' || txt[ i ] == '\t' )
+            length++;
+        else
+            break;
+    }
+    remove( pos, pos + length );
+}
+
+// Löscht alle ' ', '\n', '\r', '\t' bis zu einem anderen buchstaben
+//  pos: Die Position des ersten zeichens (beginnt bei pos-1)
+void Text::removeWhitespaceBefore( int pos )
+{
+    int length = 0;
+    for( int i = pos - 1; i >= 0; i-- )
+    {
+        if( txt[ i ] == ' ' || txt[ i ] == '\n' || txt[ i ] == '\r' || txt[ i ] == '\t' )
+            length++;
+        else
+            break;
+    }
+    remove( pos - length, pos );
+}
+
 void Text::setPrecision( int p ) // setzt die Anzahl der Nachkommastellen bei doubles
 {
     precision = p;
@@ -778,6 +810,35 @@ bool Text::hat( const char *t ) const
     return 0;
 }
 
+// Überprüft, ob im Text der Inhalt eines anderen Textes vorkommt
+//  t: Der Text, nach dessen Inhalt gesucht werden soll
+//  return: (true), wenn der Inhalt des Textes vorkommt. (false) sonnst
+//  pos: die position an der die zeichenkette im string beginnen soll
+bool Text::hatAt( int pos, Text *t ) const
+{
+    bool ret = 0;
+    if( t->getLength() > 0 ) // Auf unsinnige übergabe prüfen
+        ret = hatAt( pos, t->getText() ); // prüfen
+    t = t->release(); // Übergabe loslassen
+    return ret;
+}
+
+// Überprüft, ob im Text eine bestimmte Zeichenkette vorkommt
+//  t: Die Zeichenkette, nach der gesucht werden soll
+//  return: (true), wenn die Zeichenkette vorkommt. (false) sonnst
+//  pos: die position an der die zeichenkette im string beginnen soll
+bool Text::hatAt( int pos, const char *t ) const
+{
+    int tl = (int)strlen( t ); // Länge der Übergabe
+    int txl = getLength(); // Länge des Textes
+    if( tl <= 0 || tl + pos > txl ) // Auf unsinnige übergabe prüfen
+        return 0;
+    bool b = 1;
+    for( int i = 0; i < tl; ++i ) // Text überprüfen
+        b &= txt[ pos + i ] == t[ i ];
+    return b;
+}
+
 bool Text::hat( char c ) const // enthält c
 {
     int l = getLength(); // Text Länge

+ 16 - 0
Text.h

@@ -190,6 +190,12 @@ namespace Framework
         //  i: Das wie vielte Vorkommen des Textinhaltes gelöscht werden soll
         //  t: Der Text, dessen i-tes Vorkommen gelöscht werden soll
         __declspec( dllexport ) void remove( int i, Text *t );
+        // Löscht alle ' ', '\n', '\r', '\t' bis zu einem anderen buchstaben
+        //  pos: Die Position des ersten zeichens
+        __declspec( dllexport ) void removeWhitespaceAfter( int pos );
+        // Löscht alle ' ', '\n', '\r', '\t' bis zu einem anderen buchstaben
+        //  pos: Die Position des ersten zeichens (beginnt bei pos-1)
+        __declspec( dllexport ) void removeWhitespaceBefore( int pos );
         // Setzt die Anzahl der Nachkommastellen beim Anhängen von Kommazahlen
         //  p: Die Anzahl der Stellen nach dem Komma
         __declspec( dllexport ) void setPrecision( int p );
@@ -215,6 +221,16 @@ namespace Framework
         //  t: Die Zeichenkette, nach der gesucht werden soll
         //  return: (true), wenn die Zeichenkette vorkommt. (false) sonnst
         __declspec( dllexport ) bool hat( const char *t ) const;
+        // Überprüft, ob im Text der Inhalt eines anderen Textes vorkommt
+        //  t: Der Text, nach dessen Inhalt gesucht werden soll
+        //  return: (true), wenn der Inhalt des Textes vorkommt. (false) sonnst
+        //  pos: die position an der die zeichenkette im string beginnen soll
+        __declspec( dllexport ) bool hatAt( int pos, Text *t ) const;
+        // Überprüft, ob im Text eine bestimmte Zeichenkette vorkommt
+        //  t: Die Zeichenkette, nach der gesucht werden soll
+        //  return: (true), wenn die Zeichenkette vorkommt. (false) sonnst
+        //  pos: die position an der die zeichenkette im string beginnen soll
+        __declspec( dllexport ) bool hatAt( int pos, const char *t ) const;
         // Überprüft, ob im Text ein bestimmtes Zeichen vorkommt
         //  c: Das Zeichen, nach dem gesucht werden soll
         //  return: (true), wenn das Zeichen vorkommt. (false) sonnst

+ 724 - 0
XML.cpp

@@ -0,0 +1,724 @@
+#include "XML.h"
+
+using namespace Framework;
+using namespace XML;
+
+// Erstellt ein XML Element
+//  string: entweder der name des Elements oder ein XML Text der geparsed werden soll
+Element::Element( Text string )
+    : Element( string, 0 )
+{}
+
+// Erstellt ein XML Element
+//  string: entweder der name des Elements oder ein XML Text der geparsed werden soll
+//  zParent: Ein Zeiger auf das eltern element (ohne erhöhten reference Counter)
+Element::Element( Text string, Element *zParent )
+{
+    ref = 1;
+    children = new RCArray< Element >();
+    attributes = new RCArray< Text >();
+    attributeValues = new RCArray< Text >();
+    text = new Text();
+    name = new Text();
+    string.removeWhitespaceAfter( 0 );
+    string.removeWhitespaceBefore( string.getLength() );
+    setText( string );
+    if( string[ 0 ] == '<' && string[ string.getLength() - 1 ] == '>' )
+    {
+        string.removeWhitespaceAfter( 1 );
+        string.removeWhitespaceBefore( string.getLength() - 1 );
+        int nameEnd = 0;
+        for( int i = 1; i < string.getLength(); i++ )
+        {
+            if( ( string[ i ] < 'a' || string[ i ] > 'z' ) &&
+                ( string[ i ] < 'A' || string[ i ] > 'Z' ) &&
+                ( string[ i ] < '0' || string[ i ] > '9' ) )
+            {
+                nameEnd = i;
+                break;
+            }
+        }
+        name->setText( string.getTeilText( 1, nameEnd ) );
+        if( string.hatAt( string.getLength() - 1 - name->getLength(), name->getText() ) || string[ string.getLength() - 2 ] == '/' )
+        {
+            string.removeWhitespaceAfter( nameEnd );
+            // parse attributes
+            int start = nameEnd;
+            while( string[ nameEnd ] != '>' && string[ nameEnd ] != '/' )
+            {
+                for( int i = nameEnd + 1; i < string.getLength(); i++ )
+                {
+                    if( ( string[ i ] < 'a' || string[ i ] > 'z' ) &&
+                        ( string[ i ] < 'A' || string[ i ] > 'Z' ) &&
+                        ( string[ i ] < '0' || string[ i ] > '9' ) )
+                    {
+                        nameEnd = i;
+                        break;
+                    }
+                }
+                Text *attrName = string.getTeilText( start, nameEnd );
+                string.removeWhitespaceAfter( nameEnd );
+                if( string[ nameEnd ] == '=' )
+                {
+                    string.removeWhitespaceAfter( nameEnd + 1 );
+                    Text value = "";
+                    if( string[ nameEnd + 1 ] == '"' )
+                    {
+                        bool esc = 0;
+                        start = nameEnd + 2;
+                        for( int i = nameEnd + 2; string[ i ]; i++ )
+                        {
+                            if( string[ i ] == '\\' )
+                                esc = !esc;
+                            if( string[ i ] == '"' && !esc )
+                            {
+                                nameEnd = i + 1;
+                                break;
+                            }
+                        }
+                        value.setText( string.getTeilText( start, nameEnd - 1 ) );
+                    }
+                    if( string[ nameEnd + 1 ] == '\'' )
+                    {
+                        bool esc = 0;
+                        start = nameEnd + 2;
+                        for( int i = nameEnd + 2; string[ i ]; i++ )
+                        {
+                            if( string[ i ] == '\\' )
+                                esc = !esc;
+                            if( string[ i ] == '\'' && !esc )
+                            {
+                                nameEnd = i + 1;
+                                break;
+                            }
+                        }
+                        value.setText( string.getTeilText( start, nameEnd - 1 ) );
+                    }
+                    setAttribute( attrName->getText(), value );
+                }
+                else
+                    setAttribute( attrName->getText(), "" );
+                attrName->release();
+                string.removeWhitespaceAfter( nameEnd );
+                start = nameEnd;
+            }
+            if( string[ string.getLength() - 2 ] != '/' )
+            {
+                string.removeWhitespaceBefore( string.getLength() - 1 - name->getLength() );
+                if( string[ string.getLength() - 2 - name->getLength() ] == '/' )
+                {
+                    string.removeWhitespaceBefore( string.getLength() - 2 - name->getLength() );
+                    if( string[ string.getLength() - 3 - name->getLength() ] == '<' )
+                    {
+                        text->setText( string.getTeilText( nameEnd + 1, string.getLength() - 3 - name->getLength() ) );
+                        // parse children
+                        text->removeWhitespaceAfter( 0 );
+                        text->removeWhitespaceBefore( text->getLength() );
+                        if( text->getText()[ 0 ] == '<' && text->getText()[ text->getLength() - 1 ] == '>' )
+                        {
+                            int start = 0;
+                            while( start < text->getLength() )
+                            {
+                                bool esc = 0;
+                                bool inString1 = 0;
+                                bool inString2 = 0;
+                                int poc = 0;
+                                bool lastSlash = 0;
+                                bool lastOpen = 0;
+                                bool openSlash = 0;
+                                for( int i = 0; text->getText()[ i ]; i++ )
+                                {
+                                    switch( text->getText()[ i ] )
+                                    {
+                                    case '\\':
+                                        esc = !esc;
+                                        lastSlash = 0;
+                                        lastOpen = 0;
+                                        break;
+                                    case '"':
+                                        if( !esc && !inString2 )
+                                            inString1 = !inString1;
+                                        esc = 0;
+                                        lastSlash = 0;
+                                        lastOpen = 0;
+                                        break;
+                                    case '\'':
+                                        if( !esc && !inString1 )
+                                            inString2 = !inString2;
+                                        esc = 0;
+                                        lastSlash = 0;
+                                        lastOpen = 0;
+                                        break;
+                                    case '<':
+                                        if( !inString1 && !inString2 )
+                                        {
+                                            if( poc == 0 )
+                                                lastOpen = 1;
+                                            poc++;
+                                        }
+                                        esc = 0;
+                                        lastSlash = 0;
+                                        break;
+                                    case '/':
+                                        if( !inString1 && !inString2 )
+                                        {
+                                            lastSlash = 1;
+                                            if( lastOpen )
+                                                openSlash = 1;
+                                        }
+                                        esc = 0;
+                                        lastSlash = 0;
+                                        lastOpen = 0;
+                                        break;
+                                    case '>':
+                                        if( !inString1 && !inString2 )
+                                        {
+                                            poc--;
+                                            if( poc == 0 && (lastSlash || openSlash) )
+                                            {
+                                                Text *str = text->getTeilText( start, i + 1 );
+                                                addChild( new Element( str->getText(), this ) );
+                                                str->release();
+                                                start = i + 1;
+                                            }
+                                        }
+                                        esc = 0;
+                                        lastSlash = 0;
+                                        openSlash = 0;
+                                        break;
+                                    default:
+                                        esc = 0;
+                                        if( text->getText()[ i ] != ' ' && text->getText()[ i ] != '\t' && text->getText()[ i ] != '\r' && text->getText()[ i ] != '\n' )
+                                            lastSlash = 0;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    parent = zParent;
+}
+
+Element::~Element()
+{
+    children->release();
+    attributes->release();
+    attributeValues->release();
+    text->release();
+    name->release();
+}
+
+// ändert ein attribut oder fügt eines hinzu
+//  attribut: Der Name des Attributes
+//  value: Der Wert des Attributes
+void Element::setAttribute( Text attribut, Text value )
+{
+    for( auto i = attributes->getIterator(), j = attributeValues->getIterator(); i && j; i++, j++ )
+    {
+        if( i->istGleich( attribut ) )
+        {
+            j->setText( value );
+            return;
+        }
+    }
+    attributes->add( new Text( attribut ) );
+    attributeValues->add( new Text( value ) );
+}
+
+// entfernt ein attribut
+//  attribut: Der Name des Attributes
+void Element::removeAttribute( Text attribut )
+{
+    for( int i = 0; i < attributes->getEintragAnzahl(); i++ )
+    {
+        if( attributes->z( i )->istGleich( attribut ) )
+        {
+            attributes->remove( i );
+            attributeValues->remove( i );
+            i--;
+        }
+    }
+}
+
+// fügt ein child hinzu
+//  child: Das neue Child Element
+void Element::addChild( Element *child )
+{
+    child->parent = this;
+    children->add( child );
+}
+
+// entfernt ein child
+//  zChild: das zu entfernende Child
+void Element::removeChild( Element *child )
+{
+    for( int i = 0; i < children->getEintragAnzahl(); i++ )
+    {
+        if( children->z( i ) == child )
+        {
+            children->remove( i );
+            i--;
+        }
+    }
+    child->release();
+}
+
+// entfernt das i-te child
+//  i: der Index des childs (bei 0 beginnend)
+void Element::removeChild( int i )
+{
+    children->remove( i );
+}
+
+// entfernt alle childs
+void Element::removeAllChilds()
+{
+    children->leeren();
+}
+
+// entfernt eine Liste mit childs
+//  childs: alle Childs die entfernt werden sollen
+void Element::removeChilds( RCArray<Element> *childs )
+{
+    for( auto i = childs->getIterator(); i; i++ )
+        removeChild( i->getThis() );
+    childs->release();
+}
+
+// entfernt dieses Element vom Eltern element
+void Element::remove()
+{
+    if( parent )
+        parent->removeChild( getThis() );
+}
+
+// setzt den Text in dem Element falls es keine childs gibt
+//  text: dert Text
+void Element::setText( Text text )
+{
+    this->text->setText( text );
+}
+
+// gibt den Text im Element zurück
+Text Element::getText() const
+{
+    return text->getText();
+}
+
+// gibt die Anzahl der Childs zurück
+int Element::getChildCount() const
+{
+    return children->getEintragAnzahl();
+}
+
+// gibt das i-te child zurück
+Element *Element::getChild( int i ) const
+{
+    return children->get( i );
+}
+
+// gibt das i-te child zurück (ohne erhöhten reference Counter)
+Element *Element::zChild( int i ) const
+{
+    return children->z( i );
+}
+
+// gibt einen iterator zurück mit dem durch alle childs iteriert werden kann
+Iterator< Element* > Element::getChilds() const
+{
+    return children->getIterator();
+}
+
+// gibt einen selector zurück der alle childs beinhaltet
+Editor Element::selectChildren() const
+{
+    return Editor( children->getThis() );
+}
+
+// gibt eine Liste mit childs zurück, die einen bestimmten Namen haben
+//  name: der name der Childs
+Editor Element::selectChildsByName( Text name ) const
+{
+    RCArray< Element > *tmp = new RCArray< Element >();
+    for( auto i = children->getIterator(); i; i++ )
+    {
+        if( i->getName().istGleich( name ) )
+            tmp->add( i->getThis() );
+    }
+    return Editor( tmp );
+}
+
+// gibt eine Liste mit childs zurück, die ein bestimmtes Attribut haben
+//  attribute: der name des Attributes
+Editor Element::selectChildsByAttribute( Text attribute ) const
+{
+    RCArray< Element > *tmp = new RCArray< Element >();
+    for( auto i = children->getIterator(); i; i++ )
+    {
+        if( i->hasAttribute( attribute ) )
+            tmp->add( i->getThis() );
+    }
+    return Editor( tmp );
+}
+
+// gibt eine Liste mit childs zurück, die ein bestimmtes Attribut mit einem bestimmten wert haben
+//  attribute: der name des Attributes
+//  value: der Wert des Attributes
+Editor Element::selectChildsByAttribute( Text attribute, Text value ) const
+{
+    RCArray< Element > *tmp = new RCArray< Element >();
+    for( auto i = children->getIterator(); i; i++ )
+    {
+        if( i->hasAttribute( attribute ) && i->getAttributeValue( attribute ).istGleich( value ) )
+            tmp->add( i->getThis() );
+    }
+    return Editor( tmp );
+}
+
+// gibt 1 zurück, falls ein Attribut Name existiert, 0 sonnst
+bool Element::hasAttribute( Text name ) const
+{
+    for( auto i = attributes->getIterator(); i; i++ )
+    {
+        if( i->istGleich( name ) )
+            return 1;
+    }
+    return 0;
+}
+
+// gibt die Anzahl der Attribute zurück
+int Element::getAttributeCount() const
+{
+    return attributes->getEintragAnzahl();
+}
+
+// gibt den Namen des i-ten Attributes zurück
+Text Element::getAttributeName( int i ) const
+{
+    return attributes->z( i )->getText();
+}
+
+// gibt den Wert des i-ten Attributes zurück
+Text Element::getAttributeValue( int i ) const
+{
+    return attributeValues->z( i )->getText();
+}
+
+// gibt den Wert eines Attributes zurück
+//  attribut: Der Name des Attributes
+Text Element::getAttributeValue( Text attribut ) const
+{
+    for( auto i = attributes->getIterator(), j = attributeValues->getIterator(); i && j; i++, j++ )
+    {
+        if( i->istGleich( name ) )
+            return j->getText();
+    }
+    return "";
+}
+
+// gibt einen iterator zurück mit dem durch alle Attribut Namen iteriert werden kann
+Iterator< Text* > Element::getAttributeNames() const
+{
+    return attributes->getIterator();
+}
+
+// gibt einen iterator zurück mit dem durch alle Attribut Werte iteriert werden kann
+Iterator< Text* > Element::getAttributeValues() const
+{
+    return attributeValues->getIterator();
+}
+
+// gibt den Namen des Elementes zurück zurück
+Text Element::getName() const
+{
+    return name->getText();
+}
+
+// erzeugt einen XML Text der dieses Element und alle childs beinhaltet
+Text Element::toString() const
+{
+    Text ret = "<";
+    ret += name->getText();
+    ret += " ";
+    for( auto i = attributes->getIterator(), j = attributeValues->getIterator(); i && j; i++, j++ )
+    {
+        ret += i->getText();
+        ret += "=\"";
+        ret += j->getText();
+        ret += "\"";
+        if( i.hasNext() )
+            ret += " ";
+    }
+    if( children->getEintragAnzahl() || text->getLength() )
+    {
+        ret += ">";
+        if( children->getEintragAnzahl() )
+        {
+            for( auto i = children->getIterator(); i; i++ )
+                ret += i->toString();
+        }
+        else
+            ret += text->getText();
+        ret += "</";
+        ret += name->getText();
+        ret += ">";
+    }
+    else
+        ret += "/>";
+    return ret;
+}
+
+// Erzeugt eine Kopie ohne referenzen auf dieses objekt
+Element *Element::dublicate() const
+{
+    return new Element( toString() );
+}
+
+// erhöht den reference Counter um 1 und gibt this zurück
+Element *Element::getThis()
+{
+    ref++;
+    return this;
+}
+
+// verringert den reference Counter um 1 und gibt 0 zurück
+Element *Element::release()
+{
+    if( !--ref )
+        delete this;
+    return 0;
+}
+
+
+// Erzeugt einen neuen XML Editor mit einer Liste von Objekten die editiert werden sollen
+Editor::Editor( RCArray< Element > *elements )
+{
+    this->elements = new RCArray< Element >();
+    for( auto i = elements->getIterator(); i; i++ )
+        this->elements->add( i->getThis() );
+    elements->release();
+}
+
+Editor::Editor( const Editor &e )
+    : Editor( e.elements->getThis() )
+{}
+
+Editor::~Editor()
+{
+    elements->release();
+}
+
+// ändert ein attribut oder fügt eines hinzu (auf allen elementen in der Liste)
+//  attribut: Der Name des Attributes
+//  value: Der Wert des Attributes
+void Editor::setAttribute( Text attribut, Text value )
+{
+    for( auto i = elements->getIterator(); i; i++ )
+        i->setAttribute( attribut, value );
+}
+
+// entfernt ein attribut (auf allen elementen in der Liste)
+//  attribut: Der Name des Attributes
+void Editor::removeAttribute( Text attribut )
+{
+    for( auto i = elements->getIterator(); i; i++ )
+        i->removeAttribute( attribut );
+}
+
+// fügt ein child hinzu (auf allen elementen in der Liste)
+//  child: Das neue Child Element
+void Editor::addChild( Element *child )
+{
+    for( auto i = elements->getIterator(); i; i++ )
+        i->addChild( child->dublicate() );
+    child->release();
+}
+
+// entfernt ein child (auf allen elementen in der Liste)
+//  zChild: das zu entfernende Child
+void Editor::removeChild( Element *child )
+{
+    for( auto i = elements->getIterator(); i; i++ )
+        i->removeChild( child->getThis() );
+    child->release();
+}
+
+// entfernt das i-te child (auf allen elementen in der Liste)
+//  i: der Index des childs (bei 0 beginnend)
+void Editor::removeChild( int i )
+{
+    for( auto j = elements->getIterator(); j; j++ )
+        j->removeChild( i );
+}
+
+// entfernt alle childs (auf allen elementen in der Liste)
+void Editor::removeAllChilds()
+{
+    for( auto i = elements->getIterator(); i; i++ )
+        i->removeAllChilds();
+}
+
+// entfernt eine Liste mit childs (auf allen elementen in der Liste)
+//  childs: alle Childs die entfernt werden sollen
+void Editor::removeChilds( RCArray<Element> *childs )
+{
+    for( auto i = elements->getIterator(); i; i++ )
+        i->removeChilds( childs->getThis() );
+    childs->release();
+}
+
+// entfernt dieses Element vom Eltern element (auf allen elementen in der Liste)
+void Editor::remove()
+{
+    for( auto i = elements->getIterator(); i; i++ )
+        i->remove();
+}
+
+// setzt den Text in dem Element falls es keine childs gibt (auf allen elementen in der Liste)
+//  text: dert Text
+void Editor::setText( Text text )
+{
+    for( auto i = elements->getIterator(); i; i++ )
+        i->setText( text );
+}
+
+// Gibt ein Iterator durch alle Elemente zurück
+Iterator<Element *> Editor::getIterator()
+{
+    return elements->getIterator();
+}
+
+// gibt einen selector zurück der alle childs beinhaltet
+Editor Editor::selectChildren() const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        for( auto j = i->selectChildren().getIterator(); j; j++ )
+        {
+            list->add( j->getThis() );
+        }
+    }
+    return Editor( list );
+}
+
+// gibt einen selector zurück der alle parents beinhaltet
+Editor Editor::selectParents() const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        if( i->parent )
+            list->add( i->parent->getThis() );
+    }
+    return Editor( list );
+}
+
+// gibt eine Liste mit elementen zurück, die einen bestimmten Namen haben
+//  name: der name der Childs
+Editor Editor::whereNameEquals( Text name ) const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        if( i->getName().istGleich( name ) )
+            list->add( i->getThis() );
+    }
+    return Editor( list );
+}
+
+// gibt eine Liste mit elementen zurück, die ein bestimmtes child haben
+//  name: der name des childs
+Editor Editor::whereChildWithNameExists( Text name ) const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        if( i->selectChildsByName( name ).elements->getEintragAnzahl() )
+            list->add( i->getThis() );
+    }
+    return Editor( list );
+}
+
+// gibt eine Liste mit elementen zurück, die ein bestimmtes child haben
+//  attribute: der name des attributes
+Editor Editor::whereChildWithAttributeExists( Text attribute ) const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        if( i->selectChildsByAttribute( attribute ).elements->getEintragAnzahl() )
+            list->add( i->getThis() );
+    }
+    return Editor( list );
+}
+
+// gibt eine Liste mit elementen zurück, die ein bestimmtes child haben
+//  attribute: der name des attributes
+//  value: der Wert des Attributes
+Editor Editor::whereChildWithAttributeExists( Text attribute, Text value ) const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        if( i->selectChildsByAttribute( attribute, value ).elements->getEintragAnzahl() )
+            list->add( i->getThis() );
+    }
+    return Editor( list );
+}
+
+// gibt eine Liste mit elementen zurück, die ein bestimmtes Attribut haben
+//  attribute: der name des Attributes
+Editor Editor::whereAttributeExists( Text attribute ) const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        if( i->hasAttribute( attribute ) )
+            list->add( i->getThis() );
+    }
+    return Editor( list );
+}
+
+// gibt eine Liste mit elementen zurück, die ein bestimmtes Attribut mit einem bestimmten wert haben
+//  attribute: der name des Attributes
+//  value: der Wert des Attributes
+Editor Editor::whereAttributeEquals( Text attribute, Text value ) const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        if( i->hasAttribute( attribute ) && i->getAttributeValue( attribute ).istGleich( value ) )
+            list->add( i->getThis() );
+    }
+    return Editor( list );
+}
+
+// Gibt einen Editor zurück welcher nurnoch die Elemente enthält die nicht in e sind
+//  e: Ein Editor mit elementen die nicht enthalten sein sollen
+Editor Editor::without( Editor e ) const
+{
+    RCArray<Element> *list = new RCArray<Element>();
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        bool found = 0;
+        for( auto j = e.elements->getIterator(); j; j++ )
+            found |= i._ == j._;
+        if( !found )
+            list->add( i->getThis() );
+    }
+    return Editor( list );
+}
+
+// Ruft eine funktion für jedes Element auf
+//  f: die funktion (nimmt als argument ein Element objekt ohne erhöhten reference Counter)
+void Editor::forEach( std::function< void( Element * ) > f ) const
+{
+    for( auto i = elements->getIterator(); i; i++ )
+    {
+        f( i );
+    }
+}

+ 183 - 0
XML.h

@@ -0,0 +1,183 @@
+#pragma once
+
+#include "Array.h"
+#include <functional>
+
+namespace Framework
+{
+    class Text;
+
+    namespace XML
+    {
+        class Editor;
+
+        // Ein XML element der Form <name attribut1 attribut2="value">text oder childs</name>
+        class Element
+        {
+        private:
+            int ref;
+            RCArray< Element > *children;
+            RCArray< Text > *attributes;
+            RCArray< Text > *attributeValues;
+            Text *name;
+            Text *text;
+            Element *parent;
+
+        public:
+            // Erstellt ein XML Element
+            //  string: entweder der name des Elements oder ein XML Text der geparsed werden soll
+            __declspec( dllexport ) Element( Text string );
+            // Erstellt ein XML Element
+            //  string: entweder der name des Elements oder ein XML Text der geparsed werden soll
+            //  zParent: Ein Zeiger auf das eltern element (ohne erhöhten reference Counter)
+            __declspec( dllexport ) Element( Text string, Element *zParent );
+            __declspec( dllexport ) ~Element();
+            // ändert ein attribut oder fügt eines hinzu
+            //  attribut: Der Name des Attributes
+            //  value: Der Wert des Attributes
+            __declspec( dllexport ) void setAttribute( Text attribut, Text value );
+            // entfernt ein attribut
+            //  attribut: Der Name des Attributes
+            __declspec( dllexport ) void removeAttribute( Text attribut );
+            // fügt ein child hinzu
+            //  child: Das neue Child Element
+            __declspec( dllexport ) void addChild( Element *child );
+            // entfernt ein child
+            //  zChild: das zu entfernende Child
+            __declspec( dllexport ) void removeChild( Element *child );
+            // entfernt das i-te child
+            //  i: der Index des childs (bei 0 beginnend)
+            __declspec( dllexport ) void removeChild( int i );
+            // entfernt alle childs
+            __declspec( dllexport ) void removeAllChilds();
+            // entfernt eine Liste mit childs
+            //  childs: alle Childs die entfernt werden sollen
+            __declspec( dllexport ) void removeChilds( RCArray<Element> *childs );
+            // entfernt dieses Element vom Eltern element
+            __declspec( dllexport ) void remove();
+            // setzt den Text in dem Element falls es keine childs gibt
+            //  text: dert Text
+            __declspec( dllexport ) void setText( Text text );
+            // gibt den Text im Element zurück
+            __declspec( dllexport ) Text getText() const;
+            // gibt die Anzahl der Childs zurück
+            __declspec( dllexport ) int getChildCount() const;
+            // gibt das i-te child zurück
+            __declspec( dllexport ) Element *getChild( int i ) const;
+            // gibt das i-te child zurück (ohne erhöhten reference Counter)
+            __declspec( dllexport ) Element *zChild( int i ) const;
+            // gibt einen iterator zurück mit dem durch alle childs iteriert werden kann
+            __declspec( dllexport ) Iterator< Element* > getChilds() const;
+            // gibt einen selector zurück der alle childs beinhaltet
+            __declspec( dllexport ) Editor selectChildren() const;
+            // gibt eine Liste mit childs zurück, die einen bestimmten Namen haben
+            //  name: der name der Childs
+            __declspec( dllexport ) Editor selectChildsByName( Text name ) const;
+            // gibt eine Liste mit childs zurück, die ein bestimmtes Attribut haben
+            //  attribute: der name des Attributes
+            __declspec( dllexport ) Editor selectChildsByAttribute( Text attribute ) const;
+            // gibt eine Liste mit childs zurück, die ein bestimmtes Attribut mit einem bestimmten wert haben
+            //  attribute: der name des Attributes
+            //  value: der Wert des Attributes
+            __declspec( dllexport ) Editor selectChildsByAttribute( Text attribute, Text value ) const;
+            // gibt 1 zurück, falls ein Attribut Name existiert, 0 sonnst
+            __declspec( dllexport ) bool hasAttribute( Text name ) const;
+            // gibt die Anzahl der Attribute zurück
+            __declspec( dllexport ) int getAttributeCount() const;
+            // gibt den Namen des i-ten Attributes zurück
+            __declspec( dllexport ) Text getAttributeName( int i ) const;
+            // gibt den Wert des i-ten Attributes zurück
+            __declspec( dllexport ) Text getAttributeValue( int i ) const;
+            // gibt den Wert eines Attributes zurück
+            //  attribut: Der Name des Attributes
+            __declspec( dllexport ) Text getAttributeValue( Text attribut ) const;
+            // gibt einen iterator zurück mit dem durch alle Attribut Namen iteriert werden kann
+            __declspec( dllexport ) Iterator< Text* > getAttributeNames() const;
+            // gibt einen iterator zurück mit dem durch alle Attribut Werte iteriert werden kann
+            __declspec( dllexport ) Iterator< Text* > getAttributeValues() const;
+            // gibt den Namen des Elementes zurück zurück
+            __declspec( dllexport ) Text getName() const;
+            // erzeugt einen XML Text der dieses Element und alle childs beinhaltet
+            __declspec( dllexport ) Text toString() const;
+            // Erzeugt eine Kopie ohne referenzen auf dieses objekt
+            __declspec( dllexport ) Element *dublicate() const;
+            // erhöht den reference Counter um 1 und gibt this zurück
+            __declspec( dllexport ) Element *getThis();
+            // verringert den reference Counter um 1 und gibt 0 zurück
+            __declspec( dllexport ) Element *release();
+
+            friend Editor;
+        };
+
+        // Ein XML Editor der immer gleich mehrere Elemente editieren kann
+        class Editor
+        {
+        private:
+            RCArray< Element > *elements;
+
+        public:
+            // Erzeugt einen neuen XML Editor mit einer Liste von Objekten die editiert werden sollen
+            __declspec( dllexport ) Editor( RCArray< Element > *elements );
+            __declspec( dllexport ) Editor( const Editor &e );
+            __declspec( dllexport ) ~Editor();
+            // ändert ein attribut oder fügt eines hinzu (auf allen elementen in der Liste)
+            //  attribut: Der Name des Attributes
+            //  value: Der Wert des Attributes
+            __declspec( dllexport ) void setAttribute( Text attribut, Text value );
+            // entfernt ein attribut (auf allen elementen in der Liste)
+            //  attribut: Der Name des Attributes
+            __declspec( dllexport ) void removeAttribute( Text attribut );
+            // fügt ein child hinzu (auf allen elementen in der Liste)
+            //  child: Das neue Child Element
+            __declspec( dllexport ) void addChild( Element *child );
+            // entfernt ein child (auf allen elementen in der Liste)
+            //  zChild: das zu entfernende Child
+            __declspec( dllexport ) void removeChild( Element *child );
+            // entfernt das i-te child (auf allen elementen in der Liste)
+            //  i: der Index des childs (bei 0 beginnend)
+            __declspec( dllexport ) void removeChild( int i );
+            // entfernt alle childs (auf allen elementen in der Liste)
+            __declspec( dllexport ) void removeAllChilds();
+            // entfernt eine Liste mit childs (auf allen elementen in der Liste)
+            //  childs: alle Childs die entfernt werden sollen
+            __declspec( dllexport ) void removeChilds( RCArray<Element> *childs );
+            // entfernt dieses Element vom Eltern element (auf allen elementen in der Liste)
+            __declspec( dllexport ) void remove();
+            // setzt den Text in dem Element falls es keine childs gibt (auf allen elementen in der Liste)
+            //  text: dert Text
+            __declspec( dllexport ) void setText( Text text );
+            // Gibt ein Iterator durch alle Elemente zurück
+            __declspec( dllexport ) Iterator<Element *> getIterator();
+            // gibt einen selector zurück der alle childs beinhaltet
+            __declspec( dllexport ) Editor selectChildren() const;
+            // gibt einen selector zurück der alle parents beinhaltet
+            __declspec( dllexport ) Editor selectParents() const;
+            // gibt eine Liste mit elementen zurück, die einen bestimmten Namen haben
+            //  name: der name der Childs
+            __declspec( dllexport ) Editor whereNameEquals( Text name ) const;
+            // gibt eine Liste mit elementen zurück, die ein bestimmtes child haben
+            //  name: der name des childs
+            __declspec( dllexport ) Editor whereChildWithNameExists( Text name ) const;
+            // gibt eine Liste mit elementen zurück, die ein bestimmtes child haben
+            //  attribute: der name des attributes
+            __declspec( dllexport ) Editor whereChildWithAttributeExists( Text attribute ) const;
+            // gibt eine Liste mit elementen zurück, die ein bestimmtes child haben
+            //  attribute: der name des attributes
+            //  value: der Wert des Attributes
+            __declspec( dllexport ) Editor whereChildWithAttributeExists( Text attribute, Text value ) const;
+            // gibt eine Liste mit elementen zurück, die ein bestimmtes Attribut haben
+            //  attribute: der name des Attributes
+            __declspec( dllexport ) Editor whereAttributeExists( Text attribute ) const;
+            // gibt eine Liste mit elementen zurück, die ein bestimmtes Attribut mit einem bestimmten wert haben
+            //  attribute: der name des Attributes
+            //  value: der Wert des Attributes
+            __declspec( dllexport ) Editor whereAttributeEquals( Text attribute, Text value ) const;
+            // Gibt einen Editor zurück welcher nurnoch die Elemente enthält die nicht in e sind
+            //  e: Ein Editor mit elementen die nicht enthalten sein sollen
+            __declspec( dllexport ) Editor without( Editor e ) const;
+            // Ruft eine funktion für jedes Element auf (nimmt als argument ein Element objekt ohne erhöhten reference Counter)
+            //  f: die funktion
+            __declspec( dllexport ) void forEach( std::function< void( Element * ) > f ) const;
+        };
+    }
+}