navigieren im xml von childnode zu parentnode! wie?

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von TomWi.

    navigieren im xml von childnode zu parentnode! wie?

    Hi an Alle,

    mein Problem ist, dass ich nicht weiss, wie ich in dem XML, das ihr unten seht, von den <actor>-Nodes zu den darüberliegenden <actionList>-Nodes springen kann um deren Attribut "Name" auszulesen.
    Das auslesen der ganzen <actor>-Nodes ist kein Problem.
    das mache ich so.

    VB.NET-Quellcode

    1. FahrzeugXml.Load(modell)
    2. Dim actornodelist As Xml.XmlNodeList = FahrzeugXml.SelectNodes("//value")
    3. For Each node As XmlNode In actornodelist
    4. Dim inhalt As String
    5. inhalt = node.PreviousSibling.InnerText
    6. actor_DGV.Rows.Add(inhalt)
    7. Next


    Wie komme ich jetzt zum Node<actionList>, um mir das Attribute auszulesen?

    hier nun ein Ausschnitt aus dem XML-File

    XML-Quellcode

    1. <stateEngine autoType="variant">
    2. <stateObject shortcut="" position="-1" visible="1" name="Adapter_grundtragesystem">
    3. <state>off</state>
    4. <state>on</state>
    5. <activeState>off</activeState>
    6. <description>Adapter Grundtragesys Trageerhoehung</description>
    7. <group>Zubehoer</group>
    8. <categories />
    9. </stateObject>
    10. <actionList name="Adapter_grundtragesystem_off" tags="">
    11. <action type="switch">
    12. <actor>switch_Adapter_grundtragesystem</actor>
    13. <value>0</value>
    14. <description />
    15. </action>
    16. <description />
    17. </actionList>
    18. <actionList name="Adapter_grundtragesystem_on" tags="">
    19. <action type="switch">
    20. <actor>switch_Adapter_grundtragesystem</actor>
    21. <value>1</value>
    22. <description />
    23. </action>
    24. <description />
    25. </actionList>
    26. <condition name="Set_1" tags="">
    27. <actionListName>Adapter_grundtragesystem_on</actionListName>
    28. <stateCondition>
    29. <stateObjectName>Adapter_grundtragesystem</stateObjectName>
    30. <state>on</state>
    31. <description />
    32. </stateCondition>
    33. </condition>
    34. <condition name="Set_1" tags="">
    35. <actionListName>Adapter_grundtragesystem_off</actionListName>
    36. <stateCondition>
    37. <stateObjectName>Adapter_grundtragesystem</stateObjectName>
    38. <state>off</state>
    39. <description />
    40. </stateCondition>
    41. </condition>
    42. </stateEngine>
    43. <stateEngine autoType="variant">
    44. <stateObject shortcut="" position="-1" visible="1" name="CONFIG_ICONS">
    45. <state>off</state>
    46. <state>on</state>
    47. <activeState>off</activeState>
    48. <description>Configuration_for_GUI_ICONS</description>
    49. <group>Configuration</group>
    50. <categories />
    51. </stateObject>
    52. <actionList name="CONFIG_ICONS_on" tags="">
    53. <action type="stateObject">
    54. <actor>P0354</actor>
    55. <value>on</value>
    56. <description />
    57. </action>
    58. <action type="stateObject">
    59. <actor>S02B7</actor>
    60. <value>on</value>
    61. <description />
    62. </action>
    63. <action type="stateObject">
    64. <actor>S0337</actor>
    65. <value>off</value>
    66. <description />
    67. </action>
    68. <action type="stateObject">
    69. <actor>S07HW</actor>
    70. <value>off</value>
    71. <description />
    72. </action>
    73. <action type="stateObject">
    74. <actor>S0508</actor>
    75. <value>on</value>
    76. <description />
    77. </action>
    78. <action type="stateObject">
    79. <actor>S0420</actor>
    80. <value>off</value>
    81. <description />
    82. </action>
    83. <action type="stateObject">
    84. <actor>Ersatz_FLUCX</actor>
    85. <value>on</value>
    86. <description />
    87. </action>
    88. <action type="stateObject">
    89. <actor>S04AD</actor>
    90. <value>on</value>
    91. <description />
    92. </action>
    93. <action type="stateObject">
    94. <actor>S03AT</actor>
    95. <value>on</value>
    96. <description />
    97. </action>
    98. <description />
    99. </actionList>


    Vielleicht noch ganz kurz was zu meinem vorhaben. Ich möchte alle actornodes auslesen (klappt ja schon) und dann noch von allen actionlistnodes das Attribute "Name" auslesen.
    danach soll alles in datagridviews dargestellt werden. So.
    da es nun vorkommen kann, dass ein actor mehrfach vorkommt, aber verschiedenen actionLists zugeordnet ist, muss ich nun irgendwie herausfinden, wie die actionListnodes von den actornodes heißen.

    hoffe das ich nicht zu kompliziert beschrieben.

    vielen Dank schon mal.

    Tom

    TomWi schrieb:

    Wie komme ich jetzt zum Node<actionList>, um mir das Attribute auszulesen?


    Hö? Nix einfacher als das:

    VB.NET-Quellcode

    1. For Each node As XmlNode In actornodelist
    2. Dim inhalt As String
    3. inhalt = node.PreviousSibling.InnerText
    4. actor_DGV.Rows.Add(inhalt)
    5. Dim actionListNode As XmlNode = node.ParentNode.ParentNode ' <----
    6. Next


    Das erste ParentNode navigiert zum <action> Node, das zweite zur umgebenden <actionList>
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.
    danke. Werde ich gleich mal versuchen

    Edit:

    Frage:
    Ist der ParantNode von <actor>, nicht der <action>-node?

    Edit Nr.2:
    sorry. habe falsch gelesen. da steht ja node.parentnode.parentnode und nicht node.parentnode

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „TomWi“ ()

    Hat funktioniert. Danke.
    Habe es aber leider nur mit einem ListView geschafft.

    VB.NET-Quellcode

    1. For Each actornode As XmlNode In actornodelist
    2. Dim actorInhalt As String
    3. actorInhalt = actornode.InnerText
    4. If actorInhalt = actorsearchstring Then
    5. Dim actionListnode As XmlNode = actornode.ParentNode.ParentNode
    6. Dim actionlistname As String
    7. actionlistname = actionListnode.Attributes("name").InnerText
    8. ListView1.Items.Add(actionlistname)
    9. End If
    10. Next


    wie schaffe ich es, dass die actionlistattribute des gesuchten actors in einem datagridview angezeigt werden.
    es ist nämlich so, dass jeder actor in mindestens 2 actionlists vorkommt. Also müssen auch mindestens 2 actionlists in meinen dgv angezeigt werden.
    mit

    VB.NET-Quellcode

    1. searchdgv.Rows.Add(actionlistname)

    wird leider immer nur eine actionlistnode angezeigt.

    kann wer helfen?

    edit:
    sorry für diesen Post. Der Fehler lag bei mir. Ich habe es nämlich so geschrieben.

    VB.NET-Quellcode

    1. searchdgv.rows.clear
    2. searchdgv.Rows.Add(actionlistname)


    das kann nicht funktionieren. Also Problem gelöst. Trotzdem danke

    Es ist so, dass es sein kann, dass die Actors mit gleichem Inhalt mehrmlas vorkommen und auch bisher mehrmals im DGV dargestellt werden. Aber genau das möchte ich jetzt doch nicht. Es sollen die Actors, die mehrmals vorkommen, nicht mehrmals im DGV dargestellt werden. Es sollen also keine doppelten Einträge vorkommen. Wie schaffe ich das?

    Danke

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

    Hallo,

    ich habe bei mir im Code keine ungewollten Leerzeilen. Muss also ein Darstelleungsfehler sein. Ich hab auch öfter das Problem, dass die Meldung "Ihre Sitzung ist abgelaufen" kommt. Ist das auch ein Bug vom Forum?

    Hier der Code, mit dem ich die Actor-Nodes auslese und ins DGV einfüge

    VB.NET-Quellcode

    1. Dim actornodelist As Xml.XmlNodeList = FahrzeugXml.SelectNodes("//value")
    2. For Each node As XmlNode In actornodelist
    3. Dim inhalt As String
    4. inhalt = node.PreviousSibling.InnerText
    5. dt.Rows.Add(inhalt)
    6. Next
    7. bs.DataSource = dt
    8. actorDataGridView.DataSource = bs
    9. actorDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill


    Tom

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

    jo, jetzt siehts normal aus.
    Nur beachte, dass du die ActorNodes nicht ins DGV einfügst, sondern in eine DataTable. Da sind inne Praxis schonmal Daten und Gui getrennt, und bisserl schade, wenn du das im Kopf noch vermischst, und denkst, dass du das DGV befüllst.
    Deine Xml-Query ist komisch: Du willst Actors selectiren, der Xpath selectiert aber //value, und von den Nodes selectierst du nochmal die previousSiblings. Warum selectierst du nicht gleich //actor?
    also kurzundgut könnte man formulieren:

    VB.NET-Quellcode

    1. Sub loadFahrzeuge()
    2. Dim actornodelist As Xml.XmlNodeList = FahrzeugXml.SelectNodes("//actor")
    3. For Each node As XmlNode In actornodelist
    4. dt.Rows.Add(node.InnerText)
    5. Next
    6. '...
    ungetestet - müsste funzen, wenn dein Code funzt (wasser evtl. nicht tut)
    jo, da geb ich der Recht. Der Umweg über den NextSibling ist in der Tat überflüssig.

    Mein Code funktioniet schon. Er liest mir alle Actors aus und füllt die DataTable.
    Halt eben leider auch mit den doppelt vorkommenden Actor-Values.
    Genau das möchte ich eben nicht.

    vor dem einfügen in die DataTable erstelle ich natürlich noch ne DataRow

    VB.NET-Quellcode

    1. dt.columns.Add("actor")


    habe auch schon versucht die Column auf Unique zu setzen. Nur dann kommt immer die Exception, dass die Spalte den Wert "xyz" schon hat.

    VB.NET-Quellcode

    1. dt.columns("actor").unique = True
    ups - den Witz an der Sache jetzt über die Nebenbemerkungen vergessen - Linq-Distinct():

    VB.NET-Quellcode

    1. Sub loadFahrzeuge()
    2. Dim actornodelist As Xml.XmlNodeList = FahrzeugXml.SelectNodes("//actor")
    3. For Each txt In actornodelist.Cast(Of XmlNode).Select(function(node)node.Innertext).Distinct
    4. dt.Rows.Add(txt)
    5. Next
    6. '...
    es ist ja nur eine Zeile - die's allerdings in sich hat:

    VB.NET-Quellcode

    1. For Each txt In actornodelist.Cast(Of XmlNode).Select(function(node)node.Innertext).Distinct
    hier wird mit 3 Linq-Extension-Methods gearbeitet, die quasi als "Datenverarbeitung-Strecke" einfach hintereinander geschaltet werden.
    Extensions sind Methoden, die so tun als ob sie ObjektMethoden der Objekte wären. Also die Cast()-Methode tut so als wäre sie eine XmlNodeList-ObjektMethode, und die tut nix anneres als alle Elemente der XmlNodeList auf XmlNode zu casten und als typisierte Auflistung zurückzugeben.
    Also das Ergebnis der .Cast-Methode ist ein Objekt vom Typ IEnumerable(Of XmlNode). Auf dieses Objekt kann gleich die nächste Extension angewendet werden, nämlich die .Select()-Extension. Dieser Extension muss man eine Methode mitgeben, welche genau ein Element umwandelt.
    Diese Methode habe ich als anonyme Methode notiert: function(node)node.Innertext, und da die Select-Extension an einem IEnumerable(Of XmlNode) hängt, weiß der Compiler, dass das node-Argument nichts anneres sein kann als vom Datentyp XmlNode. Ja, und die Function ruft vom node halt den Innertext ab, der ist vom Typ String.
    In Kombination mit der .Select-Methode ergibt sich nun, dass die Select-Methode die Auflistung der XmlNodes umwandelt in eine Auflistung von Strings - genau genommen in ein IEnumerable(Of String).
    Ja, und an diese Auflistung kann ich noch die Distinct-Extension dranhängen, die alle doppelt vorkommenden Strings aus dieser Auflistung entfernt.

    Uff.

    Also um das tief zu verstehen hast du jetzt folgende Schlüssel-Begriffe zu recherchieren: Datentyp, Interface, insbesondere das IEnumerable(Of T)-Interface, TypParameter (das (Of T)), anonyme Methode, Extension-Method, Linq.
    Wie du siehst, ein mächtiges Instrumentarium, und sehr hilfreich, knapp, sicher und leicht verständlich (wenn man die Sprache beherrscht) zu coden.

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