Help with replacing values in xml files

I have two xml files (ItemA.xml, ItemB.xml) linked to another xml file (Link.xml) as shown below.


<ItemA> ItemA1</ItemA>
<ItemA> ItemA2</ItemA>


<ItemB> ItemB1</ItemB>
<ItemB> ItemB2</ItemB>


<ItemA_ID> 1</ItemA_ID>
<ItemB_ID> 1</ItemB_ID>
<ItemA_ID> 2</ItemA_ID>
<ItemB_ID> 2</ItemB_ID>

I need to compare the two other xml files (ItemC.xml, ItemD.xml) with the first two mentioned above (ItemA.xml, ItemB.xml)and copy data from ItemC and ItemD to ItemA and ItemB if they don't already exist in ItemA and ItemA.

How I achieve this?

An How do I update the Link.xml with the latest ID of ItemC and ItemD created when adding data to ItemA and ItemB?


Who is Participating?
Here's a short bit about checking existing keys/values in dictionary. This is from VB6, so the Exists method then is replaced by the Contains method now:
Public PalletLog As New Dictionary 'for storing casecodes on the pallet

                    'stextin should be casecode
                    'so, check case data to see if case has been assigned to a pallet yet.
                    'first, is this case in the casetracker collection already?
                    'can't do exists; need to pull csv and check .shippingunitid
                    'If CaseTracker.Exists(sTextIn) Then
                    If PalletLog.Exists(sTextIn) Then
                        'already exists in pallet
                        MsgBox "Duplicate Scan. Please try again.", vbInformation, "Already Scanned"
                        Exit Function
                    Else  'look up case csv and add to casetracker
                        'add casecode to palletlog
                        PalletLog.Add sTextIn, Format(Now(), "yyyy-mm-dd_HhMmSS")

                    End If 'CaseTracker.Exists(sTextIn) Then

Open in new window

this code is used to check to see if a case has already been scanned and pegged to a pallet. Each case has a unique number, so if the pallet dictionary already has that case ID in it, an error will be thrown. This is older code that used CSV files rather than XML files to track the list. The CSV file is read into a dictionary in the beginning of the program, so any cases already pegged to the pallet are in the PalletLog dictionary (that code isn't here). Hopefully this gives an idea of how this can be done. I'm sure there's a lot of more advanced programmers out there than me, who have better methods. This is just one way to approach it.
I'm curious as to what you are trying to accomplish. It looks like a relational database would be better utilized to manage that data rather than 5 different xml files.

I've never compared multiple xml files, but I have read data into a dictionary variable, then used the Contains method to see if a key/value pair exists.

Adding data to an xml file is relatively easy, once you know what tags you need and where in the hierarchy to put the new lines. There are a lot of good tutorials and instructional forums on the 'net.
Geert BormansInformation ArchitectCommented:
Well, I would do such effort using XSLT
If you would be bound to XSLT1 (if for example you are in a .net environment)
you would need three transforms, one for each file you are transforming
If you would use an XSLT2 transformer such as saxon (in a java environment or command line)
you could get this done in one go

It is a straightforward task using keys in XSLT and recommended over a RDBMS approach for smaller files. For big files I would go to a repository solution in order to index the lookups.

Could be done in code (python, ruby, .... whatever too) I would still prefer an XSLT transform, would be easier to handle. Note, three transforms still could mean one XSLT program
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

vcharlesAuthor Commented:

I have to use xml with VB.NET for this project, any links addressing this type of issue would be very helpful. Thanks for your comments.

vcharlesAuthor Commented:
One idea: read each XML into a dictionary object, then loop through one dictionary and use the Contains method against another dictionary. Whatever isn't in both dictionaries gets added to another object (I'd probably create a class collection to track the tag and value, or use a dictionary object specifically for that). Once all the outstanding values are gathered, I'd add the outstanding values to the target xmls utilizing either XElement objects or XMLDocument-type objects, whichever works better in your situation.
vcharlesAuthor Commented:
I am totally lost, can you please end me an example or links on how to use dictionaries?
Here's some sample code I use in one of my programs to read XML, load dictionary objects, load a custom class, and change values in an XML branch:

    Private Sub PullXMLData()
        Dim xdoc As New XmlDocument
        xdoc.Load(sXMLPath & "lasermark.xml")
        'select node that matches parent item
        'Dim xmlNodes As XmlNodeList = xdoc.GetElementsByTagName("pn")
        'For Each node As XmlNode In xmlNodes
        '    If node.Attributes("pn").Value = MasterData.Parent_Item Then
        '        'this is the node we want
        '        sNeoorSJM = node.Attributes("neoorsjm").Value

        '    End If 'node.Attributes("pn").Value = MasterData.Parent_Item Then
        'Next 'node as XmlNOde in xmlNodes
        'let's try selective node parsing
        Dim xNodeList As XmlNodeList
        Dim xChildren As XmlNodeList
        Dim xNode As XmlNode
        Dim nod As XmlNode

        Dim iCount As Integer = 0
        Dim x As Integer = 0
        Dim y As Integer = 0
        Dim z As Integer = 0

        Dim dChildAtts() As Dictionary(Of String, String)
        Dim dChildnodesVals() As Dictionary(Of String, String)
        Dim bHasChildren As Boolean = False
        'already loaded xDoc
        xNodeList = xdoc.SelectNodes("/parts/partnumber[@pn='" & MasterData.Parent_Item & "']")
        ReDim dChildAtts(xNodeList.Count - 1)
        For Each xNode In xNodeList
            'pull the attributes of all the nodes
            dChildAtts(x) = New Dictionary(Of String, String)
            Dim childAttsCt = xNode.Attributes.Count
            If childAttsCt > 0 Then
                For y = 0 To childAttsCt - 1
                    With dChildAtts(x)
                        .Add(xNode.Attributes.Item(y).Name.ToString, xNode.Attributes.Item(y).Value.ToString)
                    End With
                Next 'y = 0 to childAttsCt - 1
            End If 'childAttsCt > 0 then
            x += 1
        Next 'xNode in xNodeList
        'now dChildAtts should hold the attributes of the partnumber nodes

        xNode = xdoc.SelectSingleNode("/parts/partnumber[@pn='" & MasterData.Parent_Item & "']/serialnumber")
        iCount = xNode.ParentNode.ChildNodes.Count
        'icount is now the total number of nodes under th parent (partnumber node)
        ReDim dChildnodesVals(iCount - 1) 'size teh array to handle all the nodes, then add the children of those nodes
        'to the dictionary
        Do While xNode IsNot Nothing
            dChildnodesVals(z) = New Dictionary(Of String, String)
            If xNode.Attributes.Count > 0 Then
                For x = 0 To (xNode.Attributes.Count - 1)
                    dChildnodesVals(z).Add(xNode.Attributes.Item(x).Name.ToString, xNode.Attributes.Item(x).Value.ToString)
                Next 'x = 0 to (xnode.attributes.count - 1)
                xChildren = xNode.ChildNodes
                For Each nod In xChildren
                    dChildnodesVals(z).Add(nod.Name.ToString, nod.InnerText.ToString)
                Next 'nod in xChildren
                dChildnodesVals(z).Add(xNode.Name.ToString, xNode.InnerText.ToString)
            End If 'xnode.attributes.count > 0 
            z += 1
            xNode = xNode.NextSibling
        Loop 'xnode isnot nothing

        'now we have a dictionary array that holds the attributes of every partnumber node (dChildAtts)
        'and a dictionary array holding a member for each child node under a particular partnumber node (dchildnodesvals)
        For y = 0 To UBound(dChildAtts)
            For Each kvp As KeyValuePair(Of String, String) In dChildAtts(y)
                Debug.Print("dChildAtts(" & y & "): " & kvp.Key & " " & kvp.Value)
            Next 'kvp in dChildAtts
        Next ' y = 0 To UBound(dChildAtts)

        For y = 0 To UBound(dChildnodesVals)
            For Each kvp As KeyValuePair(Of String, String) In dChildnodesVals(y)
                Debug.Print("dchildnodesVals(" & y & "): " & kvp.Key & " " & kvp.Value)
                Select Case LCase(kvp.Key)
                    Case "issserialized"
                        MasterData.IsSerialized = kvp.Value
                    Case "lastsnused"
                        MasterData.LastSNUsed = kvp.Value
                    Case "snprefix"
                        MasterData.SNPrefix = kvp.Value
                    Case "idnumber"
                        MasterData.IDNumber = kvp.Value
                    Case "lastcasecode"
                        MasterData.CaseCode = kvp.Value
                    Case "lastpalletcode"
                        MasterData.PalletCode = kvp.Value
                    Case "ubd"
                        MasterData.UBDLength = kvp.Value
                    Case "ubdformat"
                        MasterData.UBDFormat = kvp.Value
                    Case "datecodeformat"
                        MasterData.Date_Format = kvp.Value
                    Case "laserfilepath"
                        MasterData.Laser_File_Path = kvp.Value
                    Case "customerpn"
                        MasterData.Cust_PN = kvp.Value
                    Case "haslabels"
                        MasterData.HasLabels = kvp.Value
                    Case "usetemplate"
                        MasterData.Use_Template = kvp.Value
                    Case "templatename"
                        MasterData.Template_Name = kvp.Value
                    Case "labelfilepath"
                        MasterData.LabelFilePath = kvp.Value
                    Case "staticbarcodedata"
                        MasterData.StaticBarcodeData = kvp.Value
                    Case "bagstock"
                        MasterData.BagStock = kvp.Value
                    Case "boxstock"
                        MasterData.BoxStock = kvp.Value
                    Case "casestock"
                        MasterData.CaseStock = kvp.Value
                    Case "boxqty"
                        MasterData.Box_Qty = kvp.Value
                    Case "caseqty"
                        MasterData.Case_Qty = kvp.Value
                    Case "csvfilepath"
                        MasterData.CSVFilePath = kvp.Value
                    Case "fixturenumber"
                        MasterData.FixtureNumber = kvp.Value
                    Case "onetwolr"
                        If LCase(kvp.Value) = "onetwo" Then
                            MasterData.OneTwo = True
                        ElseIf LCase(kvp.Value) = "leftright" Then
                            MasterData.Left_Right = True
                        End If 'lcase(kvp.value) = "onetwo"
                End Select
        Next 'y = 0 To UBound(dChildnodesVals)
    End Sub
    Private Sub UpdateXML(ByVal sWhichValue As String, ByVal sNewValue As String)
        Dim xDoc As New XmlDocument
        Dim xNode As XmlNode

        xDoc.Load(sXMLPath & "lasermark.xml")
        Select Case sWhichValue
            Case "sn"
                xNode = xDoc.SelectSingleNode("/parts/partnumber/[@pn='" & MasterData.Parent_Item & "']/serialnumber/lastsnused")
            Case "caseid"
                xNode = xDoc.SelectSingleNode("/parts/partnumber/[@pn='" & MasterData.Parent_Item & "']/serialnumber/lastcasecode")
            Case "palletid"
                xNode = xDoc.SelectSingleNode("/parts/partnumber/[@pn='" & MasterData.Parent_Item & "']/serialnumber/lastpalletcode")
        End Select
        xNode.InnerText = sNewValue
        xDoc.Save(sXMLPath & "lasermark.xml")
        xNode = Nothing
        xDoc = Nothing
    End Sub

Open in new window

vcharlesAuthor Commented:
Thanks, will get back to you.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.