New tool for assisting with access namespaced xml elements
Using InfoPath lately has really made me sharpen up my knowledge of working with Xml such as querying it with XPath. Prior to the last week or so, all of the Xml that I've queried has been non-namespaced. Adding namespaces to Xml documents and nodes means that you need to set some attributes on the underlying namespace manager of the XmlDocument when you need to query it using XPath. In C# this would look similar to this:
1XmlDocument xml = new XmlDocument() ;
2xml.Load(@"C:\Temp\Groups.xml") ;
3XmlNamespaceManager mgr = new XmlNamespaceManager(xml.NameTable) ;
4
5// ADD THE NAMESPACE
6mgr.AddNamespace("tns", @"http://MarkItUp.com/ProjectDistributor/WebServices/ProjectDistributor") ;
7// SO THAT I CAN USE IT IN THIS QUERY
8XmlNodeList nodes = xml.SelectNodes(@"//tns:Group", mgr) ;
9
10mgr = new XmlNamespaceManager(xml.NameTable) ;
11// ADD THE NAMESPACE
12mgr.AddNamespace("tns", @"http://MarkItUp.com/ProjectDistributor/WebServices/ProjectDistributor") ;
13
14for (int i=0; i<nodes.Count; i++) {
15 // SO THAT I CAN USE IT IN THIS QUERY
16 Console.WriteLine(nodes[i].SelectSingleNode("tns:DisplayName", mgr).InnerText) ;
There is a similar syntax when querying xml documents from within
javascript queries in InfoPath - such as when you have javascript in a custom
task pane although the syntax is slightly different. Here is the
javascript version of the above code:
1var ns2 = "xmlns:tns='http://MarkItUp.com/ProjectDistributor/WebServices/ProjectDistributor'";
2
3myXmlDoc.setProperty("SelectionNamespaces", ns2);
4var nodes = myXmlDoc.selectNodes("//tns:Group") ;
5
6for (var i=0; i<nodes.length; i++) {
7 s += 'Group: ' + nodes[i].selectSingleNode("tns:DisplayName").text ;
8}
9document.getElementById("groupsDIV").innerHTML = s ;
As you can see, you need to get the setProperty code right and also transpose the correct xmlns namespace information. Today I wrote a little console tool which allows you to load the xml from an InfoPath form, enter the name of the node that you are looking for and it will return the correct syntax for creating the selection namespace code and querying the value from that node. Here is the output after loading an xml document with a node named my:txtUsername:
1XDocument.DOM.setProperty("SelectionNamespaces",
2 'xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2004-12-17T00-31-40"')
3var str = XDocument.DOM.selectSingleNode("//my:txtUsername")
This is a dirt simple tool - I wrote it on the bus on the way to work :-) but, I've uploaded it my ProjectDistributor account and it is available from here:
Project Distributor :: MarkItUp :: InfoPathXmlParser :: 1.0.0.0
Future plans will be to create a webpage which provides a simple UI for running that tool without having to have it on your own system. What would be nice is, after loading the xml, I should display it in a TreeView and allow the user to click on nodes and retrieve the code that way instead of having to type in a raw node name.