Put key / value array into XML document

Posted on 2008-11-14
Last Modified: 2013-11-19

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

Question by:rwallacej
    LVL 23

    Expert Comment

    by:Jens Fiederer
    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.

    Author Comment

    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

    LVL 23

    Accepted Solution

    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

    Author Comment

    thank-you very much for your help


    LVL 23

    Expert Comment

    by:Jens Fiederer
    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.

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    IT, Stop Being Called Into Every Meeting

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    Suggested Solutions

    I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
    SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
    This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
    The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…

    761 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    7 Experts available now in Live!

    Get 1:1 Help Now