• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 285
  • Last Modified:

Help with transfering data from LinkTemp.xml to Link.xml

Hello,

I am displaying data in several controls from a LinkTemp.xml files for a particular Link_ID. My goal is to transfer records from LinkTemp.xml to Link.xml when the user presses the Transfer button. How do I transfer the data to Link.xml for a particular record?  For example:

LinkTemp displays data based on the following data:
<LinkTemp>
<LinkTemp_ID>1<LinkTemp_ID>
<Receiver_ID>3<Receiver_ID>
<Donor_ID>4</Donor_ID>
</LinkTemp>
<LinkTemp>
<LinkTemp_ID>2<LinkTemp_ID>
<Receiver_ID>6<Receiver_ID>
<Donor_ID>4</Donor_ID> 
</LinkTemp>
<LinkTemp>
<LinkTemp_ID>1<LinkTemp_ID>
<Receiver_ID>3<Receiver_ID>
<Donor_ID>4</Donor_ID> 
</LinkTemp>

Open in new window


If data is being displayed for LinkTemp_ID = 2, when the user presses the Transfer button, I need to transfer values from LinkTemp.xml
<LinkTemp_ID>2<LinkTemp_ID>
<Receiver_ID>6<Receiver_ID>
<Donor_ID>4</Donor_ID> 

Open in new window

 
To Link.xml as:
<Link_ID>2<Link_ID>
<Receiver_ID>6<Receiver_ID>
<Donor_ID>4</Donor_ID> 

Open in new window


Below is the code that I’m using to display the data from LinkTemp.xml amnd to move to next records. When I press Transfer, regardless of which record I’m displaying. As mentioned, How do I modify the code to save the ID values to Link.xml?

A.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        DonorStream.Load(Application.StartupPath & "/Donor.xml") 'My.Resources.Donor)
        RecStream.Load(Application.StartupPath & "/receiver.xml") 'My.Resources.Receiver)
        LinkStream.Load(Application.StartupPath & "/link.xml") 'My.Resources.Link)
        BindNames()
        FillCombos()

    End Sub


Public Sub BindNames()

        Dim lnk As XmlNodeList = LinkStream.SelectNodes("Root/LinkTemp")
        Dim RecName As XmlNodeList = RecStream.SelectNodes("Root/Receiver")
        Dim DonorName As XmlNodeList = DonorStream.SelectNodes("Root/Donor")

        Dim donorlst As New DataTable()
        donorlst.Columns.Add("ID")
        donorlst.Columns.Add("Name")
        Dim reclst As New DataTable
        reclst.Columns.Add("ID")
        reclst.Columns.Add("Name")

        For Each n As XmlNode In lnk
            Dim rID As Integer = Val(n.ChildNodes(0).InnerText)
            Dim dID As Integer = Val(n.ChildNodes(1).InnerText)

            For Each node As XmlNode In RecName
                If node.ChildNodes(0).InnerText = rID.ToString Then
                    reclst.Rows.Add(New Object() {rID, node.ChildNodes(1).InnerText})
                End If
            Next

            For Each node As XmlNode In DonorName
                If node.ChildNodes(0).InnerText = dID.ToString Then
                    donorlst.Rows.Add(New Object() {node.ChildNodes(0).InnerText, node.ChildNodes(1).InnerText})
                    'Exit For
                End If
            Next
        Next

        CmbDonor.DataSource = donorlst
        CmbDonor.DisplayMember = "Name"
        CmbDonor.ValueMember = "ID"

        CmbRec.DataSource = reclst
        CmbRec.DisplayMember = "Name"
        CmbRec.ValueMember = "ID"
    End Sub

Public Sub FillCombos()
        Dim RecName As XmlNodeList = RecStream.SelectNodes("Root/Receiver")
        Dim DonorName As XmlNodeList = DonorStream.SelectNodes("Root/Donor")

        Dim donorlst As New DataTable()
        donorlst.Columns.Add("ID")
        donorlst.Columns.Add("Name")
        Dim reclst As New DataTable
        reclst.Columns.Add("ID")
        reclst.Columns.Add("Name")

        For Each node As XmlNode In RecName
            reclst.Rows.Add(New Object() {node.ChildNodes(0).InnerText, node.ChildNodes(1).InnerText})
        Next

        For Each node As XmlNode In DonorName
            donorlst.Rows.Add(New Object() {node.ChildNodes(0).InnerText, node.ChildNodes(1).InnerText})
        Next

        donorlst.DefaultView.Sort = "Name ASC"
        CmbDonor.DataSource = donorlst
        CmbDonor.DisplayMember = "Name"
        CmbDonor.ValueMember = "ID"

        reclst.DefaultView.Sort = "Name ASC"
        CmbRec.DataSource = reclst
        CmbRec.DisplayMember = "Name"
        CmbRec.ValueMember = "ID"

        ComboDonor.DataSource = donorlst
        ComboDonor.DisplayMember = "Name"
        ComboDonor.ValueMember = "ID"

        ComboReceiver.DataSource = reclst
        ComboReceiver.DisplayMember = "Name"
        ComboReceiver.ValueMember = "ID"

    End Sub

Open in new window


B. Move to Next record
Private Sub Next_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Next.Click
        Dim NodeCount As Integer = LinkStream.SelectNodes("Root/Link").Count

        If (NodeNumber < NodeCount) Then
            NodeNumber += 1   'Move to some next node
            Dim node As XmlNode = LinkStream.SelectSingleNode("Root/Link[" & NodeNumber & "]")
            Dim Subnode1 As XmlNode = node.ChildNodes(0)
            Dim Subnode2 As XmlNode = node.ChildNodes(1)

            CmbRec.SelectedIndex = Val(Subnode1.InnerText) - 1
            CmbDonor.SelectedIndex = Val(Subnode2.InnerText) - 1
        Else
            NodeNumber = 0   ' Reset count so start searching from zero (You can change strategy)
        End If
    End Sub

Open in new window


Thanks,

Victor
0
vcharles
Asked:
vcharles
  • 8
  • 7
1 Solution
 
MikeTooleCommented:
I would probably approach this using XElement variables and LINQ.
It would be easier if you'd made the Element names more consistent between your XML objects.
You Have (by the way, your xml syntax is wrong - you're missing the / before some closing Element names
<LinkTemp>
<LinkTemp_ID>1<LinkTemp_ID>
<Receiver_ID>3<Receiver_ID>
<Donor_ID>4</Donor_ID>
</LinkTemp>
Why not have
<Links>
   <Link>
      <ID>1</ID>
      <Receiver_ID>3</Receiver_ID>
      <Donor_ID>4</Donor_ID>
   </Link>
</Links>

Anyway, then it would be easy to use XML and LINQ to move elements between XElement instances.
0
 
MikeTooleCommented:
The attached code selects the LinkTemp node with ID = 2
It then adds it as a new child to an XElement variable (back into the original XML just for illustration) as ID = 20 with the format you want for the target XML.

You can see the added node at the bottom of the final content of XT:

<Links>
  <LinkTemp>
    <LinkTemp_ID>1</LinkTemp_ID>
    <Receiver_ID>3</Receiver_ID>
    <Donor_ID>4</Donor_ID>
  </LinkTemp>
  <LinkTemp>
    <LinkTemp_ID>2</LinkTemp_ID>
    <Receiver_ID>6</Receiver_ID>
    <Donor_ID>4</Donor_ID>
  </LinkTemp>
  <LinkTemp>
    <LinkTemp_ID>11</LinkTemp_ID>
    <Receiver_ID>3</Receiver_ID>
    <Donor_ID>4</Donor_ID>
  </LinkTemp>
  <Link>
    <Link_ID>20</Link_ID>
    <Receiver_ID>6</Receiver_ID>
    <Donor_ID>4</Donor_ID>
  </Link>
</Links>
Dim XT As XElement =
                <Links>
                    <LinkTemp>
                        <LinkTemp_ID>1</LinkTemp_ID>
                        <Receiver_ID>3</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                    <LinkTemp>
                        <LinkTemp_ID>2</LinkTemp_ID>
                        <Receiver_ID>6</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                    <LinkTemp>
                        <LinkTemp_ID>11</LinkTemp_ID>
                        <Receiver_ID>3</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                </Links>
        Dim ID = 2
        Dim GetNodeForID = From c In XT.Elements("LinkTemp")
                      Where (c.Element("LinkTemp_ID").Value = ID)
                      Select New XElement("Link",
                                          New XElement("Link_ID", ID * 10),
                                          New XElement("Receiver_ID", c.Element("Receiver_ID").Value),
                                          New XElement("Donor_ID", c.Element("Donor_ID").Value))
        XT.Add(GetNodeForID.First)

Open in new window

0
 
vcharlesAuthor Commented:
Hi,

I don't understand why you are hard coding:

Dim XT As XElement =
                <Links>
                    <LinkTemp>
                        <LinkTemp_ID>1</LinkTemp_ID>
                        <Receiver_ID>3</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                    <LinkTemp>
                        <LinkTemp_ID>2</LinkTemp_ID>
                        <Receiver_ID>6</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                    <LinkTemp>
                        <LinkTemp_ID>11</LinkTemp_ID>
                        <Receiver_ID>3</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                </Links>
        Dim ID = 2

Shouldn't you be able to use XT after you load the file (i.e.  LinkStream.Load(Application.StartupPath & "/link.xml") 'My.Resources.Link)

I showed the examples of the content of the XML files, but I didn'yt intend to use them as part of my code. Sorry for confusing the situation.

Victor
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
MikeTooleCommented:
Victor,
This was just to get some sample data into the code without going to the bother of creating/loading a file.
The code just demonstrates the ease of using LINQ to XML to select a node and then construct a new node from the data retrieved.
It would be even easier if the XML element names matched between the two documents as there would then be no need to map the names.
Mike
0
 
vcharlesAuthor Commented:
Ok, I got it.

Can you please help me with filtering the data, in Link.xml for some reason:
For Each n As XmlNode In LinkStream.SelectNodes("/root/link[ReceiverID=" & Me.TextBox2.Text & "]")
does not work.

Code:
Dim MyLink As XDocument = XDocument.Load(Server.MapPath("~/App_Data/Link.xml"))
        ''Loop Through all records in Link.xml and assign first childnode the rID and second childnode to dID
        For Each n As XmlNode In LinkStream.SelectNodes("/root/link[ReceiverID=" & Me.TextBox2.Text & "]")
            Dim rID As Integer = Val(n.ChildNodes(0).InnerText)
            Dim dID As Integer = Val(n.ChildNodes(1).InnerText)

            ' 'Loop Through all records in Receiver.xml and if ReceiverID = Textbox2.text and if the firstnode
            For Each node As XmlNode In RecName

                If node.ChildNodes(0).InnerText = rID.ToString Then
                    reclst.Rows.Add(New Object() {rID, node.ChildNodes(0).InnerText})
                End If

            Next

            For Each node As XmlNode In DonorName
                If node.ChildNodes(0).InnerText = dID.ToString Then
                    donorlst.Rows.Add(New Object() {dID, node.ChildNodes(1).InnerText})
                    ''donorlst.Rows.Add(New Object() {dID, node.ChildNodes(1).InnerText})
                End If
            Next
        Next
0
 
vcharlesAuthor Commented:
Hello,

I understand your code now, unfortunately, it's saving the data to LinkTemp.xml, I need to save the data selected from LinkTemp.xml to Link.xml. Both Link and LinkTemp files have the same format for example if you picked the values for ID=2 in Link.xml, its related values for receiver_ID and DonorID should be appended to Link.xml.
LinkTemp.xml
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Root>
  <LinkTemp>
   <LinkTemp_ID>1</LinkTemp_ID>
    <ReceiverID>1</ReceiverID>
    <DonorID>2</DonorID>
  </LinkTemp>
  <LinkTemp>
    <LinkTemp_ID>2</LinkTemp_ID>  *****Data Selected
    <ReceiverID>2</ReceiverID>
    <DonorID>3</DonorID>
  </LinkTemp>
 <LinkTemp>
    <LinkTemp_ID>3</LinkTemp_ID>
    <ReceiverID>3</ReceiverID>
    <DonorID>4</DonorID>
 </LinkTemp>
<LinkTemp>
    <LinkTempID>4</LinkTemp_ID>
    <ReceiverID>4</ReceiverID>
    <DonorID>5</DonorID>
  </LinkTemp>
 <LinkTemp>
    <LinkTemp_ID>5</LinkTemp_ID>
    <ReceiverID>5</ReceiverID>
    <DonorID>1</DonorID>
  </LinkTemp>
</Root>

If the user selects the record where LinkTemp_ID = 2 from LinkTemp.xml, Link.xml should appear as follows:

Link.xml
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Root>
  <Link>
   <Link_ID>1</Link_ID>
    <ReceiverID>1</ReceiverID>
    <DonorID>2</DonorID>
  </Link>
  <Link>
    <Link_ID>2</Link_ID>   ***Data Transfered
    <ReceiverID>2</ReceiverID>
    <DonorID>3</DonorID>
  </Link>
</Root>
0
 
MikeTooleCommented:
>>>> XT.Add(GetNodeForID.First)

As I said, I added the node back into the original xml just as an example.
To load the node into another documnent just change the object:

MyOtherXML.Add(GetNodeForID.First)
0
 
vcharlesAuthor Commented:
Hi,

I'm almost there but still getting an error . I'm using the following Link.xml file

Link.xml:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Root>
  <Link>
   <Link_ID>1</Link_ID>
    <ReceiverID>1</ReceiverID>
    <DonorID>2</DonorID>
  </Link>
  <Link>
    <Link_ID>2</Link_ID>
    <ReceiverID>2</ReceiverID>
    <DonorID>3</DonorID>
  </Link>
 <Link>
    <Link_ID>3</Link_ID>
    <ReceiverID>3</ReceiverID>
    <DonorID>4</DonorID>
 </Link>
<Link>
    <Link_ID>4</Link_ID>
    <ReceiverID>4</ReceiverID>
    <DonorID>5</DonorID>
  </Link>
 <Link>
    <Link_ID>5</Link_ID>
    <ReceiverID>5</ReceiverID>
    <DonorID>1</DonorID>
  </Link>
</Root>

I loaded it in my application with the code below:

Dim MyLink As XDocument = XDocument.Load(Server.MapPath("~/App_Data/Link.xml"))

        Dim XT As XElement =
                <Links>
                    <LinkTemp>
                        <LinkTemp_ID>1</LinkTemp_ID>
                        <Receiver_ID>3</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                    <LinkTemp>
                        <LinkTemp_ID>2</LinkTemp_ID>
                        <Receiver_ID>6</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                    <LinkTemp>
                        <LinkTemp_ID>11</LinkTemp_ID>
                        <Receiver_ID>3</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </LinkTemp>
                </Links>

        Dim ID = 2
        Dim GetNodeForID = From c In XT.Elements("LinkTemp")
                      Where (c.Element("LinkTemp_ID").Value = ID)
                      Select New XElement("Link",
                                          New XElement("Link_ID", ID * 10),
                                          New XElement("Receiver_ID", c.Element("Receiver_ID").Value),
                                          New XElement("Donor_ID", c.Element("Donor_ID").Value))
        MyLink.Add(GetNodeForID.First)

When I press the transfer button, the last record in my Link.xml should be:
 <Link>
       <Link_ID>20</Link_ID>
        <Receiver_ID>6</Receiver_ID>
         <Donor_ID>4</Donor_ID>
  </Link>


But I'm getting error message:
This operation would create an incorrectly structured document.
on line:
MyLink.Add(GetNodeForID.First)


0
 
MikeTooleCommented:
XT represented the XElement "Links" and the Add() method added to that collection.
MyLink is an XDocument and the statement tries to add a second root element, which triggers the error.
Try:

MyLink.Element("Root").Add(GetNodeForID.First)

This should add the new node to the Root element children.
0
 
vcharlesAuthor Commented:
Hi,
Below is my Link.xml file and latest code, I'm not getting an error but the data did not tranfer to the Link.xml file,
based on XT, the last record should have been:

<Link_ID>20</Link_ID>
<Receiver_ID>6</Receiver_ID>
<Donor_ID>4</Donor_ID>
</Link>


<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Root>
<Link>
<Link_ID>1</Link_ID>
<Receiver_ID>3</Receiver_ID>
<Donor_ID>4</Donor_ID>
</Link>
<Link>
<Link_ID>2</Link_ID>
<Receiver_ID>6</Receiver_ID>
<Donor_ID>4</Donor_ID>
</Link>
<Link>
<Link_ID>11</Link_ID>
<Receiver_ID>3</Receiver_ID>
<Donor_ID>4</Donor_ID>
</Link>
</Root>

Latest Code:

  Dim MyLink As XDocument = XDocument.Load(Server.MapPath("~/App_Data/Link.xml"))

        Dim XT As XElement =
                <Link>
                    <Link>
                        <Link_ID>1</Link_ID>
                        <Receiver_ID>3</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </Link>
                    <Link>
                        <Link_ID>2</Link_ID>
                        <Receiver_ID>6</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </Link>
                    <Link>
                        <Link_ID>11</Link_ID>
                        <Receiver_ID>3</Receiver_ID>
                        <Donor_ID>4</Donor_ID>
                    </Link>
                </Link>

        Dim ID = 2
        Dim GetNodeForID = From c In XT.Elements("Link")
                      Where (c.Element("Link_ID").Value = ID)
                      Select New XElement("Link",
                                          New XElement("Link_ID", ID * 10),
                                          New XElement("Receiver_ID", c.Element("Receiver_ID").Value),
                                          New XElement("Donor_ID", c.Element("Donor_ID").Value))
        MyLink.Element("Root").Add(GetNodeForID.First)
0
 
MikeTooleCommented:
When I run this code the new node appears at the end of MyLink as expected.
How were you looking at the result? It won't appear in the file unless you save the XDocument :)
This sould do it:
MyLink.Save()

Don't forget to change  New XElement("Link_ID", ID * 10), to New XElement("Link_ID", ID),
The * 10 was just there to generate a different ID
0
 
vcharlesAuthor Commented:
Thanks, I received the follwing error when I include MyLink.save()

Error: Overload  resolution failed because no accessible 'Save' accepts this number of arguments.
0
 
MikeTooleCommented:
Looking at the Intellisense, you need to give it a file path.
0
 
vcharlesAuthor Commented:
Ok, will get back to yOu later. Thanks.
0
 
vcharlesAuthor Commented:
Thank You!!
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 8
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now