InfoPath - reading template.xsd in code for type checking

InfoPath is the world's most advanced XML-based form system.  Each InfoPath document is a fully structured XML file, and the template contains the XSD schema definition for the XML file.  This includes a bunch of information such as min/max occurrences, as well as the type information for each of the elements.

Because the information for the element's type is stored separately in the xsd file, it isn't possible at runtime to workout what the type of each element is supposed to be. 
When we are given:

  • my:value1

If we can't read the template.xsd file, we don't know if that's a number, a string, a datetime nor do we know if the field is nillable.  Some fields in InfoPath, such as the boolean and the datetime fields, can't be blank.  They have to be set to nil.

 

Here's how you can read the template.xsd in code

An InfoPath Form

 

Here is an InfoPath form with a few fields

image

 

The XML File Connection

 

Add a XML File Data Connection to an existing file in the template, I use "template.xml"

image

Save the template, and now drop into the code behind.

 

Code

public void InternalStartup()
{
    EventManager.FormEvents.Loading += new LoadingEventHandler(FormEvents_Loading);
}

public void FormEvents_Loading(object sender, LoadingEventArgs e)
{
    FileQueryConnection file = this.DataConnections["template"] as FileQueryConnection;
    file.FileLocation = "template.xsd";
    file.Execute();
    XPathNavigator template = this.DataSources["template"].CreateNavigator();
    string notes = "";

    foreach (XPathNavigator nav in this.CreateNavigator().Select("//*", this.NamespaceManager))
    {
        string localname = nav.LocalName;

        XPathNavigator element = template.SelectSingleNode("//*[@name='" + localname + "']", template);
        if (element != null)
        {
            notes += string.Format("{0} is of type {1} {2}; ", localname, element.GetAttribute("type", ""), element.GetAttribute("nillable", ""));
        }
    }

    this.CreateNavigator().SelectSingleNode("/my:myFields/my:notes", this.NamespaceManager).SetValue(notes);
}

  • The interesting part is at the top, where we bait and switch the FileQueryConnection to read the template.xsd schema file instead.  Because it is a valid XML file, InfoPath will read it happily.
  • We can then map any field in the main datasource to the corresponding definition in the template, and pull out the additional metadata such as type or nillable.

 

Result

image

 

Download