tags:

views:

326

answers:

2

I've got an Xml document that both defines and references some namespaces. I load it into an XmlDocument object and to the best of my knowledge I create a XmlNamespaceManager object with which to query Xpath against. Problem is I'm getting XPath exceptions that the namespace "my" is not defined. How do I get the namespace manager to see that the namespaces I am referencing are already defined. Or rather how do I get the namespace definitions from the document to the namespace manager.

Furthermore tt strikes me as strange that you have to provide a namespace manager to the document which you create from the documents nametable in the first place. Even if you need to hardcode manual namespaces why can't you add them directly to the document. Why do you always have to pass this namespace manager with every single query? What can't XmlDocument just know?

The Code:

XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(programFiles + @"Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\HfscBookingWorkflow\template.xml");
            XmlNamespaceManager ns = new XmlNamespaceManager(xmlDoc.NameTable);

            XmlNode referenceNode = xmlDoc.SelectSingleNode("/my:myFields/my:ReferenceNumber", ns);
            referenceNode.InnerXml = this.bookingData.ReferenceNumber;

            XmlNode titleNode = xmlDoc.SelectSingleNode("/my:myFields/my:Title", ns);
            titleNode.InnerXml = this.bookingData.FamilyName;

...

The Xml:

  <?xml version="1.0" encoding="UTF-8" ?> 
  <?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:Inspection:-myXSD-2010-01-15T18-21-55" solutionVersion="1.0.0.104" productVersion="12.0.0" PIVersion="1.0.0.0" ?> 
  <?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?> 
- <my:myFields xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"&gt;
  <my:DateRequested xsi:nil="true" /> 
  <my:DateVisited xsi:nil="true" /> 
  <my:ReferenceNumber /> 
  <my:FireCall>false</my:FireCall> 

...

[UPDATE]

ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ns.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml");
ns.AddNamespace("xd", "http://schemas.microsoft.com/office/infopath/2003");
ns.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55");

This does the job, but it mean's I have to hard code to this particular xml schema. This schema represents an infopath form template. In particular the my namespace url will be different for every form template so I really don't want to hardcode this. It would be nice to find a clean way to get this namespace from the xml without resorting to Regex.

I was hoping that the XmlNamespaceManager would just sort of pick up the namespace definitions form the NameTable. I mean their in the Xml but I still have to define them.

+1  A: 

Have you defined "my" in the namespace-manager?

ns.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55");

Or better - choose something that is unlikely to conflict. It does seem odd that it didn't pick it up from the name-table, though.

Marc Gravell
NameTable is just an optimization for storing names. It has actually nothing to do with namespaces. And even if XmlNamespaceManager could infer all namespaces and prefixes from XML doc that won't help in general case because of XML namespaces nature, e.g. what would XmlNamespaceManager map "my" prefix in this case: <root> <foo xmlns:my="blah"/> <foo xmlns:my="balh-blah-blah"/></root>
Oleg Tkachenko
@Oleg - I think you should have kept your answer (instead of deleting it) - it is a good answer to the "why?".
Marc Gravell
I've not manually added it because the url for the namespace is likely to change. The fields I'm trying to get to with XPath won't.
Dan Revell
+1  A: 
ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ns.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml");
ns.AddNamespace("xd", "http://schemas.microsoft.com/office/infopath/2003");
ns.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55");

This does the job, but it mean's I have to hard code to this particular xml schema. This schema represents an infopath form template. In particular the my namespace url will be different for every form template so I really don't want to hardcode this. It would be nice to find a clean way to get this namespace from the xml without resorting to Regex.

I was hoping that the XmlNamespaceManager would just sort of pick up the namespace definitions form the NameTable. I mean their in the Xml but I still have to define them.

Dan Revell