Put key / value array into XML document


I've got an class that is serialized to XML (containing other classes) a bit like this.

The "tag" field is unique.
The "value" field contains values to use in calculations. The "value" field is populated by client system which can only provide an array of tag/values like this

Tag       Value
000A    999
000B    23
300      123

     <FieldA tag="000A" value="?"    ...other attributes... >
                    <FieldX tag="100" value="?" ...other attributes... />
                    <FieldY tag="200" value="?" ...other attributes... />
                    <FieldZ tag="300" value="?" ...other attributes... />
                        <FieldAAA tag="100" value="?" ...other attributes... />
                        <FieldBBB tag="200" value="?" ...other attributes... />
                        <FieldCCC tag="300" value="?" ...other attributes... />

     <FieldB tag="000B" value="?"    ...other fields...>
                    <FieldX tag="100" value="?" />
                    <FieldY tag="200" value="?" />
                    <FieldZ tag="300" value="?" />
     <FieldC tag="000C" value="?"    ...other attributes... >
                    <FieldX tag="100" value="?" ...other attributes... />
                    <FieldY tag="200" value="?" ...other attributes... />
                    <FieldZ tag="300" value="?" />


So I need to put the client array into the XML filling in the "value" field where the "tag" fields match.

Perhaps this could be done automatically using some databinding?
if not how do I go through all XML children, get the "tag" field and fill in the "value" field.  I don't know how to iterate through all the XML to fill in the data as there are children-of-children-of children, not just a "simple" XML.

Thanks in advance for help with the code. Hopefully I have explained things right

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jens FiedererTest Developer/ValidatorCommented:
You could use XPath constructs to select the nodes that apply, and modify them.  

If you need some help in that (after you look up the Xpath selection statements) I would be happy to guide you through it.
rwallacejAuthor Commented:
hi jensfiederer

thanks for comment, I came to the following code before your comment.
Not sure how efficient it is / how well if performs compared with XPath though, if XPath can do the same thing
comments welcome
    ''' <summary>
    ''' Search root element where there is a Tag attribute of value specified
    ''' </summary>
    ''' <param name="root"></param>
    ''' <param name="tagValue">value of tag to search for (unique)</param>
    ''' <param name="tagAttributeID">XML attribute name of Tag field</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function FindXElementRecursively(ByVal root As XElement, ByVal tagValue As String, ByVal tagAttributeID As String) As XElement
        Dim current As XElement = root
        If current.Attribute(tagAttributeID) = tagValue Then
            Return current
        End If
        Dim found As XElement
        For Each control As XElement In current.Descendants
            found = FindXElementRecursively(control, tagValue, tagAttributeID)
            If found IsNot Nothing Then
                Return found
            End If
        Return Nothing
    End Function
    ''' <summary>
    ''' Iterate through entire XML file, replace the "value" field with data where the "tag" field matches.
    ''' </summary>
    ''' <param name="filename">XML to load</param>
    ''' <param name="data">Collection of tag/values</param>
    ''' <param name="tag">XML attribute name of Tag field</param>
    ''' <remarks></remarks>
    Public Sub populateXMLwithKeyValueData(ByVal filename As String, ByVal data As System.Collections.Generic.List(Of ETData), ByVal tag As String)
            Dim reader = New XmlTextReader(filename)
            Dim readElement = XElement.Load(reader)
            Dim desc = readElement.Descendants
            For count As Integer = 0 To data.Count - 1
                Dim xe = FindXElementRecursively(desc.ElementAt(0), data(count).tag, tag)
                If xe IsNot Nothing Then
                    xe.Attribute("value").Value = data(count).value
                End If
        Catch ex As Exception
        End Try
    End Sub
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim data As New System.Collections.Generic.List(Of ETData)
        With data
            .Add(New ETData("30000", "123"))
            .Add(New ETData("100", "999"))
            .Add(New ETData("1001", "20000"))
            .Add(New ETData("2002", "12345"))
            .Add(New ETData("20000", "9171.0"))
            .Add(New ETData("......", "9171.0"))
        End With
        Call populateXMLwithKeyValueData(Server.MapPath("~/App_Data/XMLIterate.xml"), data, "tag")
    End Sub

Open in new window

Jens FiedererTest Developer/ValidatorCommented:
I don't know how the efficiency compares (you can always benchmark it), but the XPath gives you a very READABLE approach - it handles the recursion for you.  The "Select Nodes" call does the grunt work.

            XmlDocument doc = new XmlDocument();
            XmlNodeList nodes = doc.SelectNodes("//*[@value]");
            foreach (XmlNode node in nodes)
               // abuse the node by adding your info HERE

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rwallacejAuthor Commented:
thank-you very much for your help


Jens FiedererTest Developer/ValidatorCommented:
My pleasure.

XPath lets you specify node sets nicely.  As MSDN puts it:
 All <book> elements that contain at least one <excerpt> element.
 All <title> elements inside <book> elements that contain at least one <excerpt> element.
 All <author> elements that contain at least one <degree> element, and are inside of <book> elements that contain at least one <excerpt> element.
 All <book> elements that contain at least one <author> element with at least one <degree> child element.
 All <book> elements that contain at least one <excerpt> element and at least one <title> element.

and you use "@" to indicate attribute in any of those.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.