How to work this particular XML schema...

Herman

Well-known member
Joined
Oct 18, 2011
Messages
883
Location
Montreal, QC, CA
Programming Experience
10+
Hello,

I have a very old and badly written XML file, here is a sample of the data:

HTML:
<Nodes version="1">
    <Node name="root">
        <Node name="test data">
            <Node name="child list">
                <Node name="item0000000000">
                    <Node name="child list">
                        <Node name="item0000000000">
                            <Node name="child list"/>
                            <Node name="test parameters"/>
                            <Prp name="count" type="I" value="1"/>
                            <Prp name="description" type="S" value=""/>
                            <Prp name="enabled" type="B" value="0"/>
                            <Prp name="group" type="B" value="0"/>
                            <Prp name="index" type="I" value="0"/>
                            <Prp name="key" type="S" value="{4BDE1B33-B7C2-4C06-85D7-C6730F799CE2}"/>
                            <Prp name="name" type="S" value="INI-001 - Initialisation de l'environnement de tests - FinalProc"/>
                            <Prp name="stoponerror" type="I" value="0"/>
                            <Prp name="stoponexception" type="I" value="0"/>
                            <Prp name="test moniker" type="S" value="{36B361BE-E1C7-4C71-9285-47E36FAC9F6A}CloseApp"/>
                            <Prp name="timeout" type="I" value="0"/>
                        </Node>
                    </Node>
                    <Node name="test parameters"/>
                    <Prp name="count" type="I" value="1"/>
                    <Prp name="description" type="S" value=""/>
                    <Prp name="enabled" type="B" value="0"/>
                    <Prp name="group" type="B" value="0"/>
                    <Prp name="index" type="I" value="0"/>
                    <Prp name="key" type="S" value="{EF8B2E07-0724-43D1-A489-62193AB1D1DA}"/>
                    <Prp name="name" type="S" value="INI-001 - Initialisation de l'environnement de tests - MainProc"/>
                    <Prp name="stoponerror" type="I" value="0"/>
                    <Prp name="stoponexception" type="I" value="0"/>
                    <Prp name="test moniker" type="S" value="{36B361BE-E1C7-4C71-9285-47E36FAC9F6A}InitTestEnvironnement"/>
                    <Prp name="timeout" type="I" value="0"/>
                </Node>

What I would like to do is take part of the "name" property value and put it in the "description" property instead (after the fact the name property should be "INI-001" and the description property should be "Initialisation de l'environnement de tests - MainProc"...). There are thousands of nodes like this I need to correct. I cannot change the format of the file, it has to stay exactly the same. How can I address that properly in vb.net? I'm having a hard time at even fetching the right node, as they are all called Node. How can I do a search through the XmlDocument taking into account the property "name" at every level?
 
Anyone has any idea? I toyed a bit with LinqToXml but I cant seem to get anywhere... This is kind of urgent, would appreciate any help...

For the record, I got as far as listing all the child nodes inside the "test data" node like this:

        Dim XML As New XmlDocument
        XML.Load("C:\bleh.xml")

        Dim RootNode As XmlNode = XML.DocumentElement

        ' Go to the "test data" node and iterate through its children nodes.
        For Each node As XmlNode In RootNode.ChildNodes(0).ChildNodes(8).ChildNodes(0)
            For Each SubNode As XmlNode In node
                Console.WriteLine(SubNode.Attributes.GetNamedItem("name").Value)
            Next
        Next


But I have no idea how to proceed further. Essentially after that I need to go look recursively into each node for property pairs "name" and "description", and for each pair I then split the name, fit the description.... and then what? how do I save without changing the overall schema of the file?
 
You could approach this as Prp nodes that has a certain @name attribute value ("name"), work the @value attribute value, then get the sibling Prp (where @name="description")
        For Each prp In (From x In data...<Prp> Where x.@name = "name")
            Dim parts = prp.@value.Split(New String() {" - "}, StringSplitOptions.None)
            prp.@value = parts(0)
            Dim sibling = (From s In prp.Parent.<Prp> Where s.@name = "description").First
            sibling.@value = parts(1)
        Next

or you could approach the Node nodes that has Prp child nodes.
        For Each node In (From x In data...<Node> Where x.<Prp>.Count > 0)
            Dim descPrp = (From c In node.<Prp> Where c.@name = "description").First
            Dim namePrp = (From c In node.<Prp> Where c.@name = "name").First
            Dim parts = namePrp.@value.Split(New String() {" - "}, StringSplitOptions.None)
            namePrp.@value = parts(0)
            descPrp.@value = parts(1)
        Next

both these example uses the Linq XDocument for loading and saving the xml file, like this:
        Dim data = XDocument.Load("data.xml")
        ' ....
        data.Save("newdata.xml")
 
That is some slick syntax John, thanks. The sibling approach seems to be exactly what I needed, and it will take care of all nested nodes as well. I will have a go at it and post results later tomorrow.

Thanks!
 
Just a follow up, your approach worked perfectly John. Fixed my 10MB file right up in less time than it took to grab a cup of coffee. Here is the code:

    Sub FixMDS(ByVal MDSFile As String, ByVal OutputFile As String)
        Dim XMLData = XDocument.Load(MDSFile)

        For Each prp In (From x In XMLData...<Prp> Where x.@name = "name")
            Dim OriginalName = prp.@value
            Dim NewName = OriginalName.Split(" - ")(0)
            Dim NewDescription = OriginalName.Substring(NewName.Length)

            If NewDescription.Length > 3 Then
                If NewDescription.Substring(0, 3) = " - " Then NewDescription = NewDescription.Substring(3)
            End If

            prp.@value = NewName

            Dim descr = (From s In prp.Parent.<Prp> Where s.@name = "description").First
            descr.@value = NewDescription
        Next
        XMLData.Save(OutputFile)
    End Sub
 
Back
Top