C# XML-Struktur Vergleichen

TresPuntos

Cadet 4th Year
Registriert
Juni 2018
Beiträge
113
Hallo,

mit XML habe ich so meine Schwierigkeiten.
Wenn die XML Struktur genau so aussieht, soll durch meine Methode true zurückgegeben werden.
Auf die Attributwerte soll nicht geachtet werden, deshalb habe ich diese mal mit XX belegt.
Diese Attributewerte sollen allerdings enthalten sein, nur der Inhalt ist nicht relevant.
Gedacht ist, dass ich so eine XML-Datei lokal speicher und falls diese mit meiner ausgewählten übereinstimmt, soll true zurückgegeben werden.
Mein Problem ist es diese "Vorbelegung" zu realisieren bzw den Vergleich durchzuführen.
Gibt es eventuell auch eine Vergleichsmethode, die nur die Knoten von 2 XML-Dateien vergleicht?

XML:
<?xml version="XX" encoding="XX"?>
<Settings Version="XX">
  <Setting Key="XX" Description="XX" LastChanged="XX" ValueType="XX" Version="XX">
    <Value>
      <ArrayOfLLReport xmlns:xsi="XX" xmlns:xsd="XX" />
    </Value>
  </Setting>
</Settings>
 
Zuletzt bearbeitet:
Soll die Struktur genau so aussehen, oder sollen nur die gewünschten Knoten bzw. Attribute vorhanden sein?
Es gibt ja zig Arten ein XML aufzubauen, das nach dem Parsen den gleichen Inhalt wie dein Beispiel liefert, aber im Code anders aussieht.
Sinnvoll wäre vermutlich das XML zu parsen und dann über die Attribute zu vergleichen.
 
Klingt für mich eher nach einem Fall für Schema-Validierung. Du kannst ein Schema (xsd) erstellen und dein xml-File dagegen validieren.

Bei mir sieht das z.B. so aus:

C#:
        private bool ValidateConfig(Stream configStream)
        {
            logger.Info("Starting config file schema validation ...");
            iSchemaWarnings = 0;
            iSchemaErrors = 0;

            // get schema file
            var assembly = Assembly.GetExecutingAssembly();
            var resourceName = "DHP.Database.Schema.DbUpdaterConfig.xsd";
            //var auxList = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
            XmlSchema xmlSchema = XmlSchema.Read(assembly.GetManifestResourceStream(resourceName), new ValidationEventHandler(ValidationCallBack));

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
            settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
            settings.Schemas.Add(xmlSchema);
            // Create the XmlReader object.
            XmlReader reader = XmlReader.Create(configStream, settings);
            while (reader.Read()) // dummy process file
            {
            }
            reader.Close();
            if (iSchemaErrors > 0)
            {
                logger.Error("Config file schema validation finished with {0} errors!", iSchemaErrors);
                return false;
            }
            if (iSchemaWarnings > 0)
                logger.Warn("Config file schema validation finished with {0} warnings!", iSchemaWarnings);
            else
                logger.Info("Config file schema validation finished successfully.");
            return true;
        }

        // Display any warnings or errors.
        private void ValidationCallBack (object sender, ValidationEventArgs args)
        {
            if (args.Severity == XmlSeverityType.Warning)
            {
                logger.Warn("at line {1}, position {2}: {0}", args.Message, args.Exception.LineNumber, args.Exception.LinePosition);
                iSchemaWarnings++;
            }
            else
            {
                logger.Error("at line {1}, position {2}: {0}", args.Message, args.Exception.LineNumber, args.Exception.LinePosition);
                iSchemaErrors++;
            }
        }
 
@Renegade334
Der Aufbau soll immer so aussehen, nur die Attributwerte können unterschiedlich sein.
Falls es eine weitere Zeile oder es einen anderen Attributwert gibt, soll es false zurückgeben
 
Vllt noch eine kurze Frage, wie kann ich diese XML-Zeile in einen String umwandeln?
XML:
<Array xmlns:xsi="http://www...." xmlns:xsd="http://www...." />

Habe nämlich den Code jetzt erstellt, weil es diese Zeile bei allen "falschen" XML Dateien gibt.
Der String wird aber als Fehlerhaft angezeigt:


C#:
        private Boolean compareXML(String dateiName, String pfad)
        {
            if (dateiName.StartsWith("LLReport"))
            {
                string xml = @"<Array xmlns:xsi="http://www...." xmlns:xsd="http://www...." />";
                XmlTextReader patchxml = new XmlTextReader(pfad);
                while (patchxml.Read())
                {
                    if (patchxml.Name.Equals(xml) && patchxml.NodeType == XmlNodeType.Element)
                    {
                        return true;
                    }
                }
                return false;
            }
            return false;

        }
 
Zuletzt bearbeitet:
Das @-Zeichen vor dem String bedeutet, dass das Escape-Zeichen \ als normales Zeichen behandelt wird.
Wenn du das "-Zeichen in deinem String haben willst, muss du es escapen.
 
@Darlis Wie meinst du das?
Habe nämlich schon viele verschiedene varianten versucht, aber die Anführungszeichen werden immer zum Schließen des Strings genommen

C#:
string xml = @"<Array xmlns:xsi="http://www...." xmlns:xsd="http://www...." />";

Habe nämlich in meinen XML-Dateien erkannt, dass die unnötigen XML-Dateien das enthalten, also:
XML:
<DieserWertIstUnterschiedlich xmlns:xsi="http://www...." xmlns:xsd="http://www...." />

Also alles nach DieserWertIstUnterschiedlich ist bei diesen XML-Dateien gleich, es ist wichtig darauf zu achten, dass der Knoten in derselben Zeile geschlossen wird, ansonsten ist diese Datei nicht unnötig.

C#:
string xml = @"* xmlns:xsi="hhttp://www...." xmlns:xsd="http://www...." />";

Also müsste der String in der Art aussehen, nur bekomme ich da Fehlermeldungen.
 
Zuletzt bearbeitet:
C#:
string xmlString = "<ArrayOfLLReport xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" />"
 
Dankeschön, hätte es nämlich unnötig kompliziert gemacht.
Nur funktioniert mein Code nichtmehr:

C#:
public Boolean compareXML(String dateiName, String pfad)
        {
            //sucht die XML-Dateien mit einem Grundgerüst -> die keine Änderung zur Standardanwendung haben
            if (dateiName.StartsWith("LLReport"))
            {
                //String xml = "LLReport";
                string xml = "<ArrayOfLLReport" + " xmlns:xsi=" + '"' + @"http://www...." + '"' + " xmlns:xsd=" + '"' + @"http://www...." + '"' + " >";
                XmlTextReader patchxml = new XmlTextReader(pfad);
                while (patchxml.Read())
                {
                    if (patchxml.Name.Equals(xml) && patchxml.NodeType == XmlNodeType.Element)
                    {
                        return false;
                    }
                }
                return true;
            }
            return true;
        }

Wenn es diese Zeile in der XML gibt, soll es nämlich false zurückgeben, aber die Zeile wird einfach übersprungen und nicht erkannt. Hat davor aber geklappt wenn man zum Beispiel nach <Value> gesucht hat.
 
Warum machst du es denn weiter unnötig kompliziert, wenn es auch einfacher geht? Ich dachte mir noch, ich schlage dir aus Jux und Dollerei auch die Variante mit dem '"', also als char, vor, habe es aber gelassen da es dich verwirren könnte. Aber du hast das tatsächlich umgesetzt. Das @-Zeichen hast du leider auch nicht verstanden.

Hast du denn schon mal einen Debugger eingesetzt? Damit kannst du dir angucken, was genau da passiert.

TresPuntos schrieb:
es ist wichtig darauf zu achten, dass der Knoten in derselben Zeile geschlossen wird, ansonsten ist diese Datei nicht unnötig.
Also soll der Knoten einfach nur leer sein? Der String-Vergleich den du anstrebst wäre dann nicht ideal, da man xml-Dateien in gewissem Rahmen unterschiedlich formatieren kann.
 
Zurück
Oben