1

Following up on my previous question. I am now trying to find a specific occurrence of an XML-part. For instance in the following XML (part)

<?xml version="1.0" encoding="utf-8" ?>
<definition date="2021-04-30" version="1.01">
    <changes>
        <change number="1" date="2021-04-30" description="Added .." />
        <change number="2" date="2021-04-30" description="Changes in .." />
        <change number="3" date="2021-04-30" description="Fixed .." />
        <change number="4" date="2021-05-11" description="Added " />
    </changes>
    <general>
        <styles>
            <style name="title">
                <font name="Arial" size="12" bold="true"/>
            </style>
            <style name="general">
                <font name="Courier new" size="10" bold="true" />
            </style>
            <style name="header">
                <font name="Courier new" size="10" bold="false" />
            </style>
        </styles>
    </general>

I would like to find change number 3. I'm using Dandraka XML-Utilities to make the XML an ExpandoObject. Which should allow me to get easily to specific values. For instance, working with the above I am able to get the Definition date and version like this:

    Dim strXML As String
    strXML = File.ReadAllText("C:\Tools\ReportDefinitions.xml")
    Dim def As Object
    def = XmlSlurper.ParseText(strXML)
    Console.WriteLine(def.date)
    Console.WriteLine(def.version)

I would like to use Linq on the list: def.changes.changeList. But simply:

def.changes.changeList.where(Function(c) c.number = "1").count()

Gives an error on the where part. Have searched here on SO but most examples are in C# and translating them to VB.net ends up in something that doesn't compile. Suppose I have to Cast it but how?

In C# was able to use Linq with this:
            var iet = def.changes.changeList;
            var iets = (IEnumerable)def.changes.changeList;
            var iets2 = iets.Cast<dynamic>();
            var iets3 = iets2.FirstOrDefault(p => p.number == "3");
            int iets4 = iets3.number;
            Console.WriteLine(iets4);

Now in VB.Net I can do most of it like this:

    Dim iet As Object = def.changes.changeList
    Dim iets = CType(def.changes.changeList, IEnumerable)

But this line:

            var iets2 = iets.Cast<dynamic>();

No idea how to transform that to VB.Net..

Thanks

2
  • dynamic is how you make C# let you do late binding. I think the equivalent in VB would just be Cast(Of Object). Note that IEnumerable.Cast(Of T) will give you an IEnumerable(Of T) from an IEnumerable. Commented May 17, 2021 at 18:28
  • Hi John, I only just saw this question. I'm the owner of the library, happy to hear it's useful :-) Did the reply from Marco cover you? If yes, I'll it as a VB.Net example when I release a new version. Commented Nov 9, 2022 at 19:36

2 Answers 2

2

I installed Dandraka XML and found you an answer. The issue is that Linq does not work on just IEnumerable but needs something like IEnumerable<T>. So if you cast the changeList to the type List(Of Dandraka.XmlUtilities.ToStringExpandoObject) then you can use Linq on that. In the Linq function there is another cast to Object so we can access the dynamic properties.

Dim def = XmlSlurper.ParseText(File.ReadAllText("c:\temp\data.xml"))
Console.WriteLine("Definition date " & def.date.ToString)
Console.WriteLine("Definition version " & def.version.ToString)
Console.WriteLine()
Dim list As List(Of Dandraka.XmlUtilities.ToStringExpandoObject) = def.changes.changeList
Dim number3 As Object = list.FirstOrDefault(Function(i) CType(i, Object).number = "3")
Console.WriteLine(number3.date.ToString & " - " & number3.description.ToString)
Console.ReadLine()
Sign up to request clarification or add additional context in comments.

Comments

0

I have no knowledge about Dandraka XML which is probably a way to convert xml to objects. I would not go there, but instead use the normal System.Xml library to read the contents and find what you need using XPath. So this is not an exact answer, but more like an alternative answer to get the same result.

Dim doc As New XmlDocument()
doc.Load("c:\temp\data.xml")
Dim root As XmlNode = doc.DocumentElement
Console.WriteLine("Definition date " & root.Attributes("date").Value)
Console.WriteLine("Definition version " & root.Attributes("version").Value)
Console.WriteLine()
Dim node As XmlNode = root.SelectSingleNode("changes/change[@number='3']")
Console.WriteLine(node.Attributes("date").Value & " - " & node.Attributes("description").Value)

This will get you the following output

Definition date 2021-04-30
Definition version 1.01

2021-04-30 - Fixed ..

See also: select nodes using xpath navigation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.