Probleme beim Lesen von XML-Dateien mit verschachteltem Namespace

  • VB.NET
  • .NET 5–6

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    ErfinderDesRades schrieb:

    kannste zippen und als Datei hier anhängen.


    Ich hab mal beide Dateien, sowohl die XML als auch die daraus erstellte Klasse als VB-Datei angehängt. Beide Dateien wurden aus Datenschutzgründen anonymisiert. ;)
    Wenn du mal Zeit hast, würde ich mich freuen wenn du mal prüfst ob die Klassendatei soweit in Ordnung ist und ob du eine Idee hast wie ich mit Hilfe der Klassendatei auf die Daten zugreifen kann. Bei dem header-Element z.B. ist mir das noch nicht gelungen.

    Mit Hilfe der Klasse müsste ich doch eigentlich den kompletten Aufbau automatisch verarbeiten können. Die root Klasse AutoindexBundle hat den gleichen Namen wie der Ordner in dem sich alle Dateien dieses Typs befinden und dort wiederum finde ich alle Sub-Elemente. Wenn sich dann wiederum feststellen lässt, welches Element Sub-Elemente hat, müsste man ja dann auf die Klasse AutoindexBundleAutoindex kommen, usw.?
    Dateien
    Hiermit kann ich die xml nu prinzipiell deserialisieren.
    Aber es kommen Fehlermeldungen, die bemängeln, dass im generierten vb-Code vielerlei Datentypen fehlen, zB FileCabinetDataSource, ExtendedCondition usw.
    Also im Xml wird sich auf diese Datentypen bezogen - sie fehlen aber.
    Dateien
    • XDocDemo01.zip

      (28,46 kB, 74 mal heruntergeladen, zuletzt: )

    ErfinderDesRades schrieb:

    dass im generierten vb-Code vielerlei Datentypen fehlen, zB FileCabinetDataSource, ExtendedCondition usw.


    Die fehlenden Elemente lesen sich für mich wie Attribute, da sie in doppelten Anführungszeichen stehen <d2p1:AIDataSource i:type="d2p1:FileCabinetDataSource">.

    Aus deinem angehängtem Beispiel konnte ich jetzt nicht so viel mitnehmen, läuft leider nicht bei mir. Ich habe mir aber folgenden Code rausgenommen und bei mir getestet:

    VB.NET-Quellcode

    1. Dim bundles = New AutoindexBundle
    2. Dim seri = New XmlSerializer(bundles.GetType)
    3. Dim strm = New StreamReader(strFiles)
    4. bundles = DirectCast(seri.Deserialize(strm), AutoindexBundle)
    5. Dim xxx = 0 ' hier Haltepunkt​

    Leider läuft das aber bei bundles = auch auf die bekannte Exception "There is an error in XML document (1, 40)."
    Mir ist schon klar, dass ich hier auf einen vermeintlichen Fehler in XML hingewiesen werde aber was genau bedeuten die Zahlen in der Klammer?
    Die InnerException lautet: "<AutoindexBundle xmlns='http://dev.docuware.com/settings/settingsExchange'> was not expected."

    Was genau bedeutet das, wie kann ich hier dem Fehler weiter auf den Grund gehen?

    Zur Info: Die XML-Dateien beinhalten die komplette Konfiguration, Aufbau und Parametrierung eines Fremdsystems. Da hier sehr häufig angepasst und weiterentwickelt wird bekomme ich diese Dateien regelmäßig neu. Ich möchte damit eine Dokumentation und eine Versionsverwaltung erstellen. Da ich diese Dateien so wie sie sind auch wieder in das Fremdsystem importieren kann, gehe ich davon aus, dass die Dateien soweit OK sind.
    Das man auch in meiner Version einen Fehler bekommt, schrieb ich ja. Nur ist "mein" Fehler ein anderer. Also eine Hürde habe ich genommen, wir stehen nu vor der nächsten - das ist ein Fortschritt.
    Den Fehler, den ich behoben habe war der: In der generierten Class AutoIndexBundle befindet sich eine weitere, desselben Namens: Class AutoIndexBundle.
    Wir haben also

    VB.NET-Quellcode

    1. Public Class AutoindexBundle
    2. Partial Public Class AutoindexBundle
    3. End Class
    4. End Class

    Dein Fehler: "<AutoindexBundle ...> was not expected" ist, dass du dem Serializer die äussere class AutoIndexBundle angibst.
    Ich habe das "gelöst", indem ich im generierten Code das äussere class AutoIndexBundle entfernt habe (schaus dir nochmal an).
    Aber vlt. die bessere Lösung ist, den generierten Code zu lassen, und nur dem Serializer das innere als Ziel-Datentyp zu übergeben:

    VB.NET-Quellcode

    1. Dim bundles = New AutoindexBundle.AutoindexBundle ' das innere!!
    2. Dim seri = New XmlSerializer(bundles.GetType)
    3. Dim strm = New StreamReader(strFiles)
    4. bundles = DirectCast(seri.Deserialize(strm), AutoindexBundle)
    5. Dim xxx = 0 ' hier Haltepunkt

    Dann erhälst du "meinen Fehler", mit den fehlenden Elementen - und das ist ein Fortschritt.

    Aber vmtl. kommen wir mit diesem Ansatz nicht durch, weil die fehlenden Elemente (vmtl. Datentypen) nicht herzuschaffen sind.
    Ich hab versucht, ein Dummy-Element zu coden, hab aber nix hingekriegt, was akzeptiert worden wäre.

    Hofi1609 schrieb:

    Dokumentation und eine Versionsverwaltung
    Das könnte immer noch möglich sein. Dafür muss man ja vmtl. nur wenige xmlElemente auslesen.
    Eine Versionsverwaltung hat ja ein anderes Datenmodell, als dieses generierte AutoIndexBundle, was ja wohl grosse Teile des FremdSystem-Datenmodells abbildet.

    Also welche Daten brauchst du, und sind die auch in allen Dateien enthalten?

    Wenn sie überall an derselben Stelle vorhanden sind, kann man XPath anwenden, notfalls muss man rekursiv durchlaufen und sich eine Heuristik ausdenken, die die gewünschten Werte iwie anders identifiziert (etwa nur am ElementNamen, ohne XPath).

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hier der Ansatz mit rekursivem Durchgang. Das kann jedes Xml einlesen, und baut einen Treeview daraus.
    Das ist eiglich sehr anschaulich, sodass du dir aussuchen kannst, welche Elemente du benötigst, um irgendwas (zB ein Verwaltungs-Datenmodell) draus aufzubauen.

    Der Code ist vlt auch für andere interessant:

    VB.NET-Quellcode

    1. Private Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. Dim xdoc = XDocument.Load("..\..\AutoindexBundle\AutoindexBundle.xml")
    3. Dim recurse As Action(Of TreeNodeCollection, XElement) =
    4. Sub(nds, xel)
    5. Dim childs = xel.Elements.ToList
    6. If childs.Count = 0 Then
    7. nds.Add($"{xel.Name.LocalName}='{xel.Value}'")
    8. Else
    9. Dim nd = nds.Add($"{xel.Name.LocalName,-50}{{{xel.Name.Namespace}}}")
    10. For Each chld In childs
    11. recurse(nd.Nodes, chld)
    12. Next
    13. End If
    14. End Sub
    15. recurse(TV.Nodes, xdoc.Root)
    16. TV.ExpandAll()
    17. End Sub
    Dateien
    • XDocDemo02.zip

      (28,96 kB, 71 mal heruntergeladen, zuletzt: )

    ErfinderDesRades schrieb:

    Hier der Ansatz mit rekursivem Durchgang.

    Vielen Dank für deine Mühe und Unterstützung! :thumbsup:
    Dein rekursiver Ansatz sieht sehr vielversprechend aus. Ich hatte schon 2 andere Ansätze über xmlNode und xPath, bin damit aber auch noch nicht so richtig weitergekommen.

    Ich bin im Moment mit einer SAP Einführung und der damit verbunden Anpassung an die von mir betreute Software beschäftig. Das lässt mir leider keine bis wenig Zeit mich um meine privaten Projekte zu kümmern. Ich werde wahrscheinlich einige Tage benötigen um deinen Code zu testen.

    Hofi1609 schrieb:

    Dokumentation und eine Versionsverwaltung

    In einigen der XML-Dateien die Daten für einen Low-code Workflow Builder enthalten, welche aber mit HTML-Entity gecodet sind. Diesen möchte ich extrahieren, decodieren (das hab ich schon gelöst) und in einer lesbaren Form (als XML) speichern damit ich mit Git eine Versionsverwaltung aufbauen kann und die Inhalte schnell durchsuchen kann.
    Außerdem möchte ich alle wesentlichen Elemente in eine Datenbank überführen und dort mit entsprechenden Ergänzungen für die Erstellung einer Dokumentation versehen. Die gelieferten XML-Dateien sind je nach Art recht unterschiedlich, vor allem ist der Namenspace nicht einheitlich. Da die Originale sehr groß und unübersichtlich sind, muss ich mich da wohl durch die einzelnen Typen durchhangeln. Meine Idee war aus den Dateien eine einfache einheitliche XML ohne Namespace als Zwischenlösung zu erzeugen und dann weiter zu sehen.

    Hofi1609 schrieb:

    Meine Idee war aus den Dateien eine einfache einheitliche XML ohne Namespace
    jo, da kann das rekursive Ding helfen.
    Weil das liest alle XElemente aus - egal welcher Namespace.
    Wenn du iwann mal weisst, welche XmlElement für dein Einheits-Dingens von Belang sind, kann man - statt eines Treeviews - auch ein entsprechendes (Einheits-)XmlDocument ausgeben.