Node mapping between DOMDocuments in MSXML4

Posted on 2002-07-10
Last Modified: 2012-05-04

   I have a particular IXMLDOMNode object on a DOMDocument40. I have a second DOMDocument40, which is exactly the same as the first, with the exception that its nodes have a vital value stored in the .key property. Question is, how do I get hold of the same node in the second DOMDoc, thereby gaining access to its .key property??


Question by:NikWhitfield
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
LVL 27

Expert Comment

ID: 7144485
I presume you mean to do this generically. The problem is however that the XPath to the node in tree 1 is not obtainable by a "backward translation" API DOM call from the "currently selected node". This literally implies that when navigating in tree 1 you have to apply exactly the same navigation to tree 2.

The other alternative might be to try to construct a navigation by recursively selecting the parent node up to the root, ascertain in which position this is in the child list, and in such a way construct an XPath expression to use in the second DOM. You don't necessarily have to construct an XPath expression, since you can apply the selection to the second tree after ascertaining the "selection at this level" viz:

   function selectInTree2(tree1,tree2) {
       if IsRootNode(tree2) {
          /* at root so return root */
          return tree2.selectNode('/');
       } else {
          /* first get parent */
          parent = selectParent(tree1);
          /* and then determine which child */
          position = findChild(parent,tree1);
          /* now tree2 is equivalent to parent */
          /* so just select the nth child */
          return tree2.selectNodeByPosition(position)

if you get my drift(?)!


Author Comment

ID: 7145537
This doesn't make much sense to me.....

I can see how you'd do it with XPath, but not by using the code fragment above. Could you explain it further? I can't see how findChild would work, hence how the whole thing would work!

Much appreciated,

LVL 27

Accepted Solution

BigRat earned 100 total points
ID: 7145651
The basic problem is, given a node in a DOM in a variable x how to find the node in the other document (= other DOM).

There is no API call like x.getXPathForNode() which would return a string containing a path to the node from the root, so there only remains the possibility of doing it "by hand".

The basic idea is to work our way from x up to the root and to use the information obtained to work our way in the other document from the root down to the equivalent node x.

I assume that the documents are IDENTICAL EXCEPT FOR ATTRIBUTES! In which case the parent/child relationships between two nodes in one document are identical to those in the other.

Now if the node x (=tree1) is the root node, then we want the root node in document 2 (=tree2) hence :-

     function ....(tree1,tree2) {
       if isRootNode(tree1) then
          return tree2.selectNode('/');

That bit also terminates the search and returns the top node in document 2.

If x is not the root it MUST have a parent node. So we select it -

        parent = selectParent(tree1);
(the actual API call is tree1.parentNode())

Now x is a child of parent - but which one? It could be the only child or it could be the nth child. We need to find out which one. The call findChild() does this. This is probably the API childNodes() followed by a search through the returned list to find the child number.

When we have the child number we can use it to select the corresponding child in document 2. We can only do this when we have found the corresponding parent node, so we just simply call our functuon recursively to do this :-

      position = findChild(parent,tree1);
      /* now tree2 is equivalent to parent */
      parentintree2 = selectInTree2(parent,tree2);

and then use the position to find the node in the returned tree :-

      /* so just select the nth child */
      return parentintree2.selectNodeByPosition(position);

The last call selectNodeByPosition is simply childNodes() followed by index(position) since NodeLists can be directly indexed.

I used the named functions to hide detail away from the algorithm. I adivse you to do the same. The isRootNode() is something like paraentNode() followed by a test to see if one was selected, and if so whether it is a node or the document. No node selected or the document node implies the root (=documentElement). You could add the document nodes as extra parameters to make this sort of test easier.

I originally overwrote tree2 with the parentInTree2 which was bad coding pratice, for which I apologize!

Quiz: What Do These Organizations Have In Common?

Hint: Their teams ended up taking quizzes, too.


Author Comment

ID: 7145737
OK, I got ya. Works a treat - good use of recursion. Thanks a lot
LVL 27

Expert Comment

ID: 7145824
You managed in an hour to get all that to work! I am impressed! Thanks for the cheese.

Author Comment

ID: 7145832
Here's the code, if you ever need it (and happen to be delving into VB....)

Function getNode(pobjXMLNode As IXMLDOMNode, pobjDomDoc As DOMDocument40) As IXMLDOMNode
'* Name:        getNode
'* Description: Finds a node from one tree in another identical tree
'* Parameters:  pobjXMLNode - the node to search for. pobjDomDoc - the tree to search in
'* Returns:     IXMLDomNode - the equivalent node in the other tree
'* Notes :      A 'hard to get your head round' piece of recursion here. Continue to
'*              pass an object's parent through recursively, until it's the root node
'*              being passed, which is the terminating condition. At that point,
'*              return the Root of the searching tree, which will then be used to
'*              return the correct child recursively. Easy!
'* Created:     11/07/2002: NMW: Creation

Const PROC_NAME = "getNode"
On Error GoTo ErrorHandler

'Body Code Begins

Dim objXMLParent As IXMLDOMNode
Dim lngPosition As Long
Dim objParentInTree As IXMLDOMNode

    'Check whether this node is the tree root - if so, return it.
    If pobjXMLNode.nodeName = mcstrDOCUMENT_ROOT_NAME Then
        Set getNode = pobjDomDoc.selectSingleNode("/")
    'Not the root node, so it must have a parent - select it
        Set objXMLParent = pobjXMLNode.ParentNode
        lngPosition = Position(pobjXMLNode)
        Set objParentInTree = getNode(objXMLParent, pobjDomDoc)
        Set getNode = objParentInTree.ChildNodes(lngPosition)
    End If

'Body Code Ends


Exit Function
   Select Case Err.Number
       Case Else
            ' Then raise it
            Err.Raise gobjErr.Number, gobjErr.Source, gobjErr.Description, gobjErr.HelpFile, gobjErr.HelpContext
   End Select
End Function


Featured Post

Why You Need a DevOps Toolchain

IT needs to deliver services with more agility and velocity. IT must roll out application features and innovations faster to keep up with customer demands, which is where a DevOps toolchain steps in. View the infographic to see why you need a DevOps toolchain.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
The Confluence of Individual Knowledge and the Collective Intelligence At this writing (summer 2013) the term API ( has made its way into the popular lexicon of the English language.  A few years ago, …
Come and listen to Percona CEO Peter Zaitsev discuss what’s new in Percona open source software, including Percona Server for MySQL ( and MongoDB (…
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…

726 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