Hi, i've tried to look for some code that inserts rows. I couldn't find any answer that satisfied me, for example missing node-order. So i've created my own method and just wanted to share it (jscript) with everyone here.
It can:
-
Insert a row to a repeatinggroup
-
Insert a group which is not in default values
-
Respect the node order InfoPath expects
-
Use predicates, like my:repeating_group[3]/my:repeating_subgroup
It can't:
-
Insert multiple rows, always the first node (selectSingleNode) will be used.
-
Insert a row at a specific location in a repeating group, the new node is always inserted at the end of a repeating group.
//Inserts a node at the specified location
function InsertNode(xpath)
{
//Get reference to the sampledocument (sampledata.xml)
var domSample = XDocument.CreateDOM();
domSample.async = false;
domSample.validateOnParse = false;
domSample.load("sampledata.xml");
domSample.setProperty("SelectionNamespaces", XDocument.DOM.getProperty("SelectionNamespaces"));
//Get reference to sample node, this will be inserted into the maindom
var xpathSample = xpath;
while(xpathSample.indexOf('[') != -1 && xpathSample.indexOf(']') != -1)
{
xpathSample = xpathSample.replace(xpathSample.substring(xpathSample.indexOf('['), xpathSample.indexOf(']') + 1), "");
}
var nodeSample = domSample.selectSingleNode(xpathSample);
if(nodeSample == null) throw new Error("Unable to insert node: '" + xpathSample + "' doesn't exist in sampledata.");
//Get reference to parentnode
var xpathParent = xpath.slice(0, xpath.lastIndexOf('/'));
var nodeParent = XDocument.DOM.selectSingleNode(xpathParent);
if(nodeParent == null) throw new Error("Unable to insert node: Parent '" + xpathParent + "' doesn't exist.");
//Determine if the parentnode has a sibling that can be used as a reference
var nodeRef = null;
var nodeSampleRef = nodeSample.nextSibling;
while(nodeSampleRef != null && nodeSample.prefix == nodeSampleRef.prefix)
{
nodeRef = XDocument.DOM.selectSingleNode(xpathParent + "/" + nodeSampleRef.nodeName);
if(nodeRef != null) break;
nodeSampleRef = nodeSampleRef.nextSibling;
}
//Insert the node
try
{
nodeParent.insertBefore(nodeSample, nodeRef);
}
catch(e)
{
throw new Error("Error inserting node. Are you trying to insert an already existing node while it is non-repeating?");
}
}
//Example
function btnExample::OnClick(eventObj)
{
try
{
InsertNode("/my:root/my:repeating_group");
InsertNode("/my:root/my:repeating_group[3]/my:other_repeating_group");
InsertNode("/my:root/my:repeating_group[my:field1 = "InfoPath"]/my:group_that_is_not_in_default_values");
InsertNode("/my:root/my:group/my:group_that_is_not_in_default_values");
}
catch(e)
{
XDocument.UI.Alert(e.message);
}
}
I've tested a bit in InfoPath 2007, but might be possible still some errors occur in specific situations. Let me know.
Albert
edit: forgot to metion you can't use [ and ] inside the predicates right now. And it might be a good idea to return the newly inserted node. If i can find some time i might take care of both.