XPathNavigator.AppendChild() Replaces Instead of Appends - InfoPath Dev
in

InfoPath Dev

XPathNavigator.AppendChild() Replaces Instead of Appends

Last post 03-05-2013 10:57 AM by abcolson. 1 replies.
Page 1 of 1 (2 items)
Sort Posts: Previous Next
  • 03-04-2013 11:24 AM

    • abcolson
    • Not Ranked
      Male
    • Joined on 12-12-2007
    • San Diego
    • Posts 20

    XPathNavigator.AppendChild() Replaces Instead of Appends

    Greetings,

    I have encountered some peculiar behavior which I can neither explain nor find referenced in the documentation.  I am using InfoPath 2010 on Windows 7 and am developing a C# form.  The structure of the underlying data is something like:

    <Submission>
        <Patient>
            <Isolation />
        </Patient>
    </Submission>

    What I am attempting to do is programmatically add an Isolation to a Patient when a user clicks a button. (For debugging purposes I have simulated this event in the FormEvents_Loading method to eliminate other factors...the results are the same.)  At present, the patient initializes with 1 Isolation from the default template.

    I can get an XPathNavigator to a Patient just fine, and even inspect and change attributes if I please.  When it comes time to call AppendChild() to add an Isolation I make sure the NodeType is Element and then call AppendChild().  Now, in the absence of any exceptions, I would expect a new Isolation to be created and added under Patient; but alas, this is not the case.  What appears to be happening is that the new Isolation is created but instead of appending to the list of Isolations in Patient, the original Isolation from the default template is replaced with the new one.  I can find no documentation regarding this behavior whether it be about methodologies for calling AppendChild() or invalid states of XPathNavigators where the method does nothing.  So, does anyone have an idea on what could be happening?

    Below is some code which shows what I am doing.  I have tried using various overloads of AppendChild(); this example just shows one case:

    const string ATTR_1 = NODE_NAME_PATIENT_ISOLATIONS_PATIENT;
    const string ATTR_2 = NODE_NAME_PATIENT_ISOLATIONS_ISOLATION;

     

    for (int i = 1; i <= 2; i++)

    {

      string localName = NODE_NAME_PATIENT_ISOLATIONS.Substring(2);

      XmlDocument doc = new XmlDocument();

      XmlElement  ele = doc.CreateElement(DATA_PREFIX, localName, DATA_NAMESPACE);

     

      ele.Attributes.Append(doc.CreateAttribute(ATTR_1));

      ele.Attributes.Append(doc.CreateAttribute(ATTR_2));

     

      if( i == 1 ) ele.SetAttribute(ATTR_1, "99");

      ele.SetAttribute(ATTR_2, i.ToString());

     

      XPathNavigator n1 = ele.CreateNavigator();

     

      if (patient.NodeType != XPathNodeType.Element) patient.MoveToParent();

     

      patient.AppendChild(n1);

      XPathNodeIterator kids = patient.Select(NODE_NAME_PATIENT_ISOLATIONS, nsManagerMain);

     

      MessageBox.Show("Total Kids = " + kids.Count);

    }

    In this scenario I create a loop to apend 2 Isolation elements to an existing Patient.  When the loop starts the patient already has 1 isolation (from the template).  I would therefore expect 3 total isolations after the loop finished.  The first isolation added sets 2 attributes, one to the counter value and the other to an example value of 99.  After the first iteration the OuterXml for the patient looks as follows (notice only 1 Isolation):

    <d:Daily_Audit_Form_-_Patients xmlns:d=\"http://schemas.microsoft.com/office/infopath/2003/ado/dataFields\" >
          <d:Daily_Audit_Form_-_Patient_Isolations Patient_ID="99" Isolation_ID="1"/>
    </d:Daily_Audit_Form_-_Patients>

    The second iteration only sets the attribute with the counter value and does not use the example value of 99.  After the second iteration the OuterXml looks as follows:

    <d:Daily_Audit_Form_-_Patients xmlns:d=\"http://schemas.microsoft.com/office/infopath/2003/ado/dataFields\" >
          <d:Daily_Audit_Form_-_Patient_Isolations Patient_ID="" Isolation_ID="2"/>
    </d:Daily_Audit_Form_-_Patients>

    In this case, in addition to there only being 1 Isolation node, notice also that the example value of 99 is missing.  This tells me that the AppendChild() method is not a no-op and that in fact the new Isolation node is replacing the existing node, or, at the very least, is merely overcopying the original attributes.

    The only thing I can suspect this point is that Isolations do have optional child elements but the schema defines the occurrences as being from 0 to unbounded.  And, there are also repeating tables bound to these children elements on the form but as this is not a GUI issue I can't fathom that that is material to what is happening...

    So, any clues?

    Thanks,
    Tony

  • 03-05-2013 10:57 AM In reply to

    • abcolson
    • Not Ranked
      Male
    • Joined on 12-12-2007
    • San Diego
    • Posts 20

    Re: XPathNavigator.AppendChild() Replaces Instead of Appends

    Chalk this one up to me being stupid (sort of) ... :|

    In short, I had a Patient_Change event handler that was deleting the Isolations right when I was adding them.  Sounds crazy, right?  Well, let me explain since this might be biting someone else...

    I was porting over an InfoPath 2003 form into InfoPath 2010. Sigh...as we all know everything changed in the guts of InfoPath; moving from IXMLDOMNode to XPathNavigator as well as ... process behavior

    When I was porting over the IP 2003 files I basically created the new IP 2010 project and then with the structure in place started copying over the .xsl and .cs files.  Of course, the .cs files didn't even come close to compiling.  So, the first pass was to take care of all the syntax errors and make the obvious changes (like IXMLDOMNode to XPathNavigator, etc.).  In event handlers, this included adapting phrases like if( e.Operation == "Insert" ) to if( e.Operation == XmlOperation.Insert ).  No big deal, except the function of the operation changed.  In IP 2003 the insertion of a child node did not trip the event handler of the parent(s) whereas (apparently) in IP 2010 is does. So, what was happening was that a special insert situation in my parent (Patient) event handler (which worked fine in IP 2003) was now being tripped in IP 2010 when I inserted a child (Isolation) node.  I was able to deduce this by trying to programatically add multiple Patient nodes (which worked) and then adding in a repeating section into the GUI and trying to add multiple Isolations (which didn't work and yeilded the same weird behavior in the initial post).  After observing this framework of behavior I started thinking of event handling and BAM!  I found the cause and fix as noted above.  Frustrating as @#$#@%$@ !!!

    Hope this helps someone...

    Tony

Page 1 of 1 (2 items)
Copyright © 2003-2019 Qdabra Software. All rights reserved.
View our Terms of Use.