Operations on DOM nodes take a long time when you process a very large amount of data in InfoPath 2003 (888702)



The information in this article applies to:

  • Microsoft Office InfoPath 2003, Service Pack 1 (SP1)
  • Microsoft Office InfoPath 2003

SYMPTOMS

In Microsoft Office InfoPath 2003, when you process a very large amount of data, you may notice that the operations on Document Object Model (DOM) nodes take a long time.

CAUSE

Whenever data in an InfoPath DOM is changed, InfoPath 2003 maintains the earlier version of the data so that you can use the Undo command on the Edit menu if you want to undo the change. When the amount of data in the DOM is very large, InfoPath 2003 may take longer than you expect to display the earlier version of the data after you run the Undo command.

WORKAROUND

To work around this problem, follow these steps:
  1. Create a new DOMDocument object.
  2. Use this DOMDocument object to perform the change to the data in the form. Because the DOMDocument object that you create does not maintain the earlier version of the data, the DOMDocument object will not experience the performance slowdown that occurs in the main InfoPath DOM.
  3. Copy the data from the new DOMDocument object back into the main InfoPath DOM.

STATUS

Microsoft has confirmed that this is a problem in the Microsoft products that are listed in the "Applies to" section.

MORE INFORMATION

Steps to reproduce the problem

  1. Create a new blank InfoPath 2003 form, and set the form code language to JScript. To do this, follow these steps:
    1. Start InfoPath 2003.
    2. On the File menu, click Design a Form.
    3. In the Design a Form pane, click New Blank Form.
    4. On the Tools menu, click Form Options.
    5. In the Form Options dialog box, click the Advanced tab, select JScript from the Form code language list, and then click OK.
  2. Add a Repeating Table control and three Button controls to the form. To do this, follow these steps:
    1. In the Controls pane, click Repeating Table under Repeating and Optional. In the Number of columns box, click 3, and then click OK.
    2. Insert three Button controls above the Repeating Table control by clicking and then dragging the Button control from the Controls pane to the form.
  3. Add form code to the three buttons. To do this, follow these steps:
    1. Right-click the first Button control, and then click Button Properties.
    2. In the Button Properties dialog box, type Setup Data in the Label box, and then type SetupData in the ID box.
    3. Click Edit Form Code. The following lines of code are the default code.
      function SetupData::OnClick(eventObj)
      {
       // Write your code here.
      }
       
      
      Replace this default code with the following lines of code.
      function SetupData::OnClick(eventObj)
      {
       //Get a reference to the sampledata DOM.
       var objSampleDataDOM = XDocument.DOM;
       
       //Create a new DOMDocument, and load the template into it. This makes it easier
       //to create new rows for the repeating table.
       var objTemplateDoc = XDocument.CreateDOM();
       objTemplateDoc.validateOnParse = false;
       objTemplateDoc.load("template.xml");
       
       //Set the SelectionNamespaces to the same value as the main DOM.
       var strSelectionNamespaces = objSampleDataDOM.getProperty("SelectionNamespaces");
       objTemplateDoc.setProperty("SelectionNamespaces", strSelectionNamespaces );
        
       //Get a reference to group1 in the main data source.
       var objGroup1 = objSampleDataDOM.selectSingleNode("/my:myFields/my:group1");
       
       //Remove all the current elements.
       objcurrentChildren = objGroup1.selectNodes("*");
       objcurrentChildren.removeAll();
       
       //Get a reference to group2 in the template document.
       var objGroup2 = objTemplateDoc.selectSingleNode("/my:myFields/my:group1/my:group2");
       
       //Add many group2s to the group1.
       for (var i = 0; i < 200; i++)
       {
        //Clone the group2 node.
        var objClonedGroup2 = objGroup2.cloneNode( true );
        
        //Set the values of the field.
        objClonedGroup2.selectSingleNode("my:field1").text = i;
        objClonedGroup2.selectSingleNode("my:field2").text = (i%2 == 0);
        
        //Append the cloned group2 to group1.
        objGroup1.appendChild( objClonedGroup2 );
       }
      }
      
      Note The script for Setup Data generates lots of test data for the form.
    4. Right-click the second Button control, and then click Button Properties.
    5. In the Button Properties dialog box, type Slow Operation in the Label box, and then type SlowOperation in the ID box.
    6. Click Edit Form Code. The following lines of code are the default code.
      function SlowOperation::OnClick(eventObj)
      {
       // Write your code here.
      }
       
      
      Replace this default code with the following lines of code.
      function SlowOperation::OnClick(eventObj)
      {
       //Get a reference to the sampledata DOM.
       var objSampleDataDOM = XDocument.DOM;
       
       //Get a reference to group1 in the main data source.
       var objGroup1 = objSampleDataDOM.selectSingleNode("/my:myFields/my:group1");
       
       //Get a list of all the group2 elements where "field2" is "true".
       var objGroup2List = objGroup1.selectNodes("my:group2[my:field2 = 'True']");
       
       //Enumerate through the nodes.
       var objCurrentGroup2 = null;
       while (objCurrentGroup2 = objGroup2List.nextNode())
       {
        //Remove each group2 node in the list.
        objGroup1.removeChild( objCurrentGroup2 );
       }
      }
      
      Note The script for Slow Operation removes all the rows of data where field2 contains the word "True."
    7. Right-click the third Button control, and then click Button Properties.
    8. In the Button Properties dialog box, type Fast Operation in the Label box, and then type FastOperation in the ID box.
    9. Click Edit Form Code. The following lines of code are the default code.
      function FastOperation::OnClick(eventObj)
      {
       // Write your code here.
      }
      
      Replace this default code with the following lines of code.
      function FastOperation::OnClick(eventObj)
      {
       //Get a reference to the sampledata DOM.
       var objSampleDataDOM = XDocument.DOM;
       
       //Create a new DOMDocument, and load the template into it.
       var objTemporaryDoc = new ActiveXObject("MSXML2.DOMDocument.5.0");
       objTemporaryDoc.validateOnParse = false;
       objTemporaryDoc.load("template.xml");
       
       //Set the SelectionNamespaces to the same value as the main DOM.
       var strSelectionNamespaces = objSampleDataDOM.getProperty("SelectionNamespaces");
       objTemporaryDoc.setProperty("SelectionNamespaces", strSelectionNamespaces );
        
       //Get a reference to group1 in the temporary document.
       var objTemporaryGroup1 = objTemporaryDoc.selectSingleNode("/my:myFields/my:group1");
       
       //Remove all the child elements.
       var objTemporaryChildren = objTemporaryGroup1.selectNodes("*");
       objTemporaryChildren.removeAll();
       
       //Get a reference to group1 in the main data source.
       var objMainGroup1 = objSampleDataDOM.selectSingleNode("/my:myFields/my:group1");
       
       //Get a list of all the group2 elements where "field2" is NOT "true".
       var objGroup2List = objMainGroup1.selectNodes("my:group2[not(my:field2 = 'True')]");
       
       //Enumerate through the nodes.
       var objCurrentGroup2 = null;
       while (objCurrentGroup2 = objGroup2List.nextNode())
       {
        //Copy the group2 node into the temporary group1.
        var clonedGroup2 = objCurrentGroup2.cloneNode(true);
        objTemporaryGroup1.appendChild( clonedGroup2 );
       }
       
       //Replace the main group1 node with the temporary group1 node.
       objSampleDataDOM.selectSingleNode("/my:myFields").replaceChild( objTemporaryGroup1, 
        objMainGroup1 );
      }
       
      
      Note The script for Fast Operation copies all the rows of data where field2 contains the word "False" into a new DOMDocument object. The script then replaces the original table with the new table.
    10. On the File menu, click Exit to close the Microsoft Script Editor.
To test the form, follow these steps:
  1. On the Standard toolbar, click Preview Form.
  2. Click Setup Data. It may take several seconds for this script to run.
  3. Click Slow Operation. Note the time that is required for this script to run.
  4. Click Setup Data again to reset the test data.
  5. Click Fast Operation. This script runs much faster than the script in step 3 because the new DOMDocument object does not maintain the earlier version of the data.

Modification Type:MajorLast Reviewed:4/1/2005
Keywords:kbtshoot kbprb kbbug KB888702 kbAudDeveloper kbAudITPRO