Solved

Node mapping between DOMDocuments in MSXML4

Posted on 2002-07-10
6
289 Views
Last Modified: 2012-05-04
Hi,

   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??

Cheers,

Nik
0
Comment
Question by:NikWhitfield
  • 3
  • 3
6 Comments
 
LVL 27

Expert Comment

by:BigRat
Comment Utility
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(?)!

HTH
0
 

Author Comment

by:NikWhitfield
Comment Utility
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,

Nik
0
 
LVL 27

Accepted Solution

by:
BigRat earned 100 total points
Comment Utility
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('/');
       else
          .....

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!

HTH
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:NikWhitfield
Comment Utility
OK, I got ya. Works a treat - good use of recursion. Thanks a lot
0
 
LVL 27

Expert Comment

by:BigRat
Comment Utility
You managed in an hour to get all that to work! I am impressed! Thanks for the cheese.
0
 

Author Comment

by:NikWhitfield
Comment Utility
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

    'RECURSIVE TERMINATING CONDITION
    '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
    Else
        Set objXMLParent = pobjXMLNode.ParentNode
        lngPosition = Position(pobjXMLNode)
        'RECURSIVE CALL MADE HERE
        Set objParentInTree = getNode(objXMLParent, pobjDomDoc)
        Set getNode = objParentInTree.ChildNodes(lngPosition)
    End If

'Body Code Ends

LeaveProc:

Exit Function
ErrorHandler:
   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
'**********************************************************************

Ta
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
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.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

762 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

6 Experts available now in Live!

Get 1:1 Help Now