none
Redefining attribute node text value using the Attribute Property and Index results in reording the attributes in the XML RRS feed

  • Question

  • Please refer to cross-post at: 

    http://www.vbaexpress.com/forum/showthread.php?65491-Setting-quot-Text-quot-value-of-XML-Attribute-Node-Changes-Node-Index-Order


    Greg Maxey Please visit my website at: http://gregmaxey.mvps.org/word_tips.htm

    Sunday, July 14, 2019 3:09 PM

Answers

All replies

  • Hi Greg,

    Please provide all the details directly here.

    http://www.vbaexpress.com site requires a membership, and doesn't allow to download the attached document.


    Sunday, July 14, 2019 3:32 PM

  • I recently put together a process to populate a userform Listbox using data in a document CustomXMLPart using child nodes of a parent ListEntry node:

    Click image for larger version. 

Name:	1.jpg 
Views:	1 
Size:	38.8 KB 
ID:	24589

    Next, I thought it would be an interesting exercise to see if I could use attributes (vice child nodes) e.g.,:

    Click image for larger version. 

Name:	2.jpg 
Views:	1 
Size:	33.2 KB 
ID:	24590

    However, I discovered that whenever I attempted to redefine the attribute values using the .Attributes property and index, the order of the attributes was altered in the XML e.g.,:

    m_oCXNode.Attributes(1).Text = txtEditName
    m_oCXNode.Attributes(2).Text = txtEditRank
    m_oCXNode.Attributes(3).Text = txtEditSN

    resulted in the following:

    Click image for larger version. 

Name:	3.jpg 
Views:	1 
Size:	44.1 KB 
ID:	24591

    I've worked around this issue in the attached but would sure like to understand why that happens or get a suggestion on a better forum to publish this issue.

    I don't know how to attach the file :-(


    Greg Maxey Please visit my website at: http://gregmaxey.mvps.org/word_tips.htm


    • Edited by Greg Maxey Sunday, July 14, 2019 3:42 PM
    Sunday, July 14, 2019 3:41 PM
  • Hi Greg,

    • The images are still invisible.
      There is a small toolbar on top where the last icon on the right side allows to insert images on this forum. Otherwise, all images you linked, they don't show up.
    • And there are no attachments here on the forum.


    Sunday, July 14, 2019 3:46 PM
  • Hmm, I can see the images I posted here.

    I published the file to my website:

    https://gregmaxey.comword_tip_resources/Load%20and%20Append%20CustomXMLPart%20to%20from%20UserForm%20Ver%201.2.zip


    Greg Maxey Please visit my website at: http://gregmaxey.mvps.org/word_tips.htm


    • Edited by Greg Maxey Sunday, July 14, 2019 3:59 PM
    Sunday, July 14, 2019 3:58 PM
  • Hi Greg,

    There is a conceptual issue here at hand.

    1. Generally speaking, XML attributes have no order. It is because attribute names must be unique for attributes under some parent element.
    2. On the other hand, XML elements have a sequential order, that's why XPath expression could be used as follows: /elementName[position]

    Sunday, July 14, 2019 4:56 PM
  • Yitzhak,

      I don't quite understand you.  The attribute names are unique.  Each ListEntry node has three attributes named "Name", "Rank" and "Serial_Number".  When ListEntry nodes are created using the "Add" process, they are defined in order

    1. Name 2. Rank 3. Serial_Number  and appear in the resulting XML in that order.

    However when the Edit process is used, the order of the Name and Rank attributes are changed.  Don't understand why.

    'Wierdness occurs here.  For whatever reason the position of the Name and Rank attributes are swapped as a result of the following lines of code.  Name which was formerly the Attribute(1)
        'becomes Atributes(2) and Rank formerly Attribute(2) becomes Attribute(1) ?????
        'm_oCXNode.Attributes(1).Text = txtEditName
        'm_oCXNode.Attributes(2).Text = txtEditRank
        'm_oCXNode.Attributes(3).Text = txtEditSN
        '###################################################################
        '*******************************************************************
        'Using this as a work around
        Set oAttr = m_oCXNode.SelectSingleNode(m_oCXNode.XPath & "/@Name")
        oAttr.Text = txtEditName
        Set oAttr = m_oCXNode.SelectSingleNode(m_oCXNode.XPath & "/@Rank")
        oAttr.Text = txtEditRank
        Set oAttr = m_oCXNode.SelectSingleNode(m_oCXNode.XPath & "/@Serial_Number")
        oAttr.Text = txtEditSN


    Greg Maxey Please visit my website at: http://gregmaxey.mvps.org/word_tips.htm

    Sunday, July 14, 2019 5:07 PM
  • Hi Greg,

    Quite simple: "...XML attributes have no order..." based on the XML specification.



    Sunday, July 14, 2019 5:08 PM
  • Yitzhak,

      Yes, I suppose that does make sense.  You certainly seem to know what you are talking about (I don't).  I just cobbled that process together. 

      So, changing the scope a bit, then what I have called a work around is more like the way (one way) it must be done.  I don't know if you looked at the document with the complete process, but it you did I would certainly appreciate in suggestions for improvement.

      My goal was to have a completely self contained data source for the userform listbox.

    Thanks


    Greg Maxey Please visit my website at: http://gregmaxey.mvps.org/word_tips.htm

    Sunday, July 14, 2019 6:46 PM
  • Hi Greg,

    If the order is important for you, I would suggest to revert your implementation back to using XML elements.

    Sunday, July 14, 2019 6:47 PM
  • Yitzhak,

      Well now that I know there is no order and have a way to explicitly get the attribute node I need to update, it really doesn't matter.

       I was just asking if you have any general suggestions for improving the process.


    Greg Maxey Please visit my website at: http://gregmaxey.mvps.org/word_tips.htm

    Sunday, July 14, 2019 7:18 PM
  • Hi Greg,

    "... Well now that I know there is no order and have a way to explicitly get the attribute node I need to update, it really doesn't matter..."

    I hope I answered your question regarding the non-existing sort order of XML attributes.

    Please don't forget to click "Mark as Answer" the response(s) that resolved your issue. This can be beneficial to other community members reading this thread.

    Monday, July 15, 2019 2:19 AM
  • Yitzhak,

      I suppose I am just having trouble understanding why the attributes can appear in a logical order and then simply be reordered.  The following code run in Word illustrates:

    Sub Test() Dim lngIndex As Long Dim oCXPart As CustomXMLPart, oCXNode As CustomXMLNode On Error Resume Next Set oCXPart = ActiveDocument.CustomXMLParts.SelectByNamespace("http//form_data_attr@namespace.com").Item(1) If Err.Number = 0 Then oCXPart.Delete Set oCXPart = ActiveDocument.CustomXMLParts.Add("<FormData xmlns='http//form_data_attr@namespace.com'/>") For lngIndex = 1 To 5 oCXPart.AddNode oCXPart.SelectSingleNode("ns0:FormData"), "ListEntry", , , msoCustomXMLNodeElement Set oCXNode = oCXPart.SelectSingleNode("ns0:FormData").LastChild oCXNode.AppendChildNode "Name", , msoCustomXMLNodeAttribute, "Name-" & lngIndex oCXNode.AppendChildNode "Rank", , msoCustomXMLNodeAttribute, "Rank-" & lngIndex oCXNode.AppendChildNode "Serial_Number", , msoCustomXMLNodeAttribute, lngIndex Next lngIndex

    Stop 'Select one of the ListEntry nodes. Set oCXNode = oCXPart.SelectSingleNode("/ns0:FormData[1]/ListEntry[2]") With oCXNode 'Get the values of the indexed attributes. MsgBox .Attributes(1).BaseName & ": " & .Attributes(1).Text MsgBox .Attributes(2).BaseName & ": " & .Attributes(2).Text MsgBox .Attributes(3).BaseName & ": " & .Attributes(3).Text 'All return correct attribute "unique" name and value. 'Now attempt to modify values of the three indexed attributes. .Attributes(1).Text = "Some new name" MsgBox .Attributes(1).BaseName & ": " & .Attributes(1).Text 'Attribute(1) is now named "Rank" and its value is unchanged. .Attributes(2).Text = "Some new rank" MsgBox .Attributes(2).BaseName & ": " & .Attributes(2).Text 'Attribute(2) is now named "Name" and its value is correct as modified. .Attributes(3).Text = "Some new serial number" MsgBox .Attributes(3).BaseName & ": " & .Attributes(3).Text 'Attribute(3) is still named "Serial_Number" and its value is correct as modified. End With End Sub

    Here is what the XML looks like at the stop point:

    And this is after the code runs to completion:

    Well, to close the loop, here is some code that does correctly modify the attributes and leaves them in the order created:

    Sub Test2()
    Dim lngIndex As Long
    Dim oCXPart As CustomXMLPart, oCXNode As CustomXMLNode
      On Error Resume Next
      Set oCXPart = ActiveDocument.CustomXMLParts.SelectByNamespace("http//form_data_attr@namespace.com").Item(1)
      If Err.Number = 0 Then oCXPart.Delete
      Set oCXPart = ActiveDocument.CustomXMLParts.Add("<FormData xmlns='http//form_data_attr@namespace.com'/>")
      On Error GoTo 0
      For lngIndex = 1 To 5
        oCXPart.AddNode oCXPart.SelectSingleNode("ns0:FormData"), "ListEntry", , , msoCustomXMLNodeElement
        Set oCXNode = oCXPart.SelectSingleNode("ns0:FormData").LastChild
        oCXNode.AppendChildNode "Name", , msoCustomXMLNodeAttribute, "Name-" & lngIndex
        oCXNode.AppendChildNode "Rank", , msoCustomXMLNodeAttribute, "Rank-" & lngIndex
        oCXNode.AppendChildNode "Serial_Number", , msoCustomXMLNodeAttribute, lngIndex
      Next lngIndex
      'Select one of the ListEntry nodes.
      Set oCXNode = oCXPart.SelectSingleNode("/ns0:FormData[1]/ListEntry[2]")
      With oCXNode
        'Get the values of the indexed attributes.
        MsgBox .Attributes(1).BaseName & ": " & .Attributes(1).Text
        MsgBox .Attributes(2).BaseName & ": " & .Attributes(2).Text
        MsgBox .Attributes(3).BaseName & ": " & .Attributes(3).Text
        'All return correct attribute "unique" name and value.
        'Now modify values of the exmplicity named attributes.
        .SelectSingleNode(.XPath & "/@Name").Text = "Some new name"
        MsgBox .Attributes(1).BaseName & ": " & .Attributes(1).Text 'Attribute(1) is now named "Rank" and its value is unchanged.
        .SelectSingleNode(.XPath & "/@Rank").Text = "Some new rank"
        MsgBox .Attributes(2).BaseName & ": " & .Attributes(2).Text 'Attribute(2) is now named "Name" and its value is correct as modified.
        .SelectSingleNode(.XPath & "/@Serial_Number").Text = "Some new serial number"
        MsgBox .Attributes(3).BaseName & ": " & .Attributes(3).Text 'Attribute(3) is still named "Serial_Number" and its value is correct as modified.
        'However, when it is all said and done, the attributes are reindexed in the correct order.  Very weird ;-)
        MsgBox .Attributes(1).BaseName & ": " & .Attributes(1).Text
        MsgBox .Attributes(2).BaseName & ": " & .Attributes(2).Text
        MsgBox .Attributes(3).BaseName & ": " & .Attributes(3).Text
    
      End With
    End Sub


    Greg Maxey Please visit my website at: http://gregmaxey.mvps.org/word_tips.htm

    Monday, July 15, 2019 1:45 PM