开发者

Can i create a XmlNamespaceManager object from the xml file i am about to read?

开发者 https://www.devze.com 2023-02-03 10:41 出处:网络
I have some c# code running on sharepoint that i use to check inside the xml of an infopath document to see if i should checking the document or discard the document.

I have some c# code running on sharepoint that i use to check inside the xml of an infopath document to see if i should checking the document or discard the document.

开发者_如何转开发The code is working fine for a couple of different form templates i have created but is failing on my latested one. I have discovered that the XmlNamespaceManager i am creating contains the wrong diffinition for the "MY" namepsace.

I'll try to explain

I have this code to decalre my XmlNamespaceManager

NameTable nt = new NameTable();
NamespaceManager = new XmlNamespaceManager(nt);

// Add prefix/namespace pairs to the XmlNamespaceManager.
NamespaceManager.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
NamespaceManager.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml");
NamespaceManager.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");            
NamespaceManager.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-07-14T13:45:59");
NamespaceManager.AddNamespace("xd", "http://schemas.microsoft.com/office/infopath/2003");`

I can then use the following line of code to search for the xml i am after

XPathNavigator nav = xml.CreateNavigator().SelectSingleNode("//my:HasSaved", NamespaceManager);

nav.Value then gets be the data i want.

This all works fine on a couple of my form templates. I ahve a new form template and have discovered that i need to use thi line instead

NamespaceManager.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-11-30T17:39:37");

The date is different.

My problem is that i cannot add this twice as only 1 set of forms will work.

So my question is. Is there a way i can generate the NamespaceManager object from the XML file as this is all contained in the header? I have not been able to find a simple way round this.


I found a way of doing this. Instead of adding the "my" namespace it can be pulled from the XmlDocument object. This might just be a bit of luck that it works this way but i'm happy with it.

NamespaceManager.AddNamespace("my", formXml.DocumentElement.NamespaceURI

formXML is an XmlDocument created from the infopath XML


One option would be to try to load the xml node using the first namespace, if that doesn't give any results, call PushScope(), override the first namespace definition, select, etc...

var doc = new XmlDocument();


doc.LoadXml(@"<?xml version=""1.0""?>
      <root xmlns:my=""http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-11-30T17:39:37"" value=""1"">
           <my:item>test</my:item>
      </root>");


var nameTable = new NameTable();

var namespaceManager = new XmlNamespaceManager(nameTable);


namespaceManager.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");

namespaceManager.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml");

namespaceManager.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");            

namespaceManager.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-07-14T13:45:59");

namespaceManager.AddNamespace("xd", "http://schemas.microsoft.com/office/infopath/2003");


// n will be null since the namespace url doesn't match

var n = doc.SelectSingleNode("descendant::my:item", namespaceManager);


namespaceManager.PushScope();

namespaceManager.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-11-30T17:39:37");


// will work

n = doc.SelectSingleNode("descendant::my:item", namespaceManager);


namespaceManager.PopScope();

Another option is to parse the attributes in the header and look for any contained namespaces

foreach(XmlAttribute attribute in doc.DocumentElement.Attributes)
{
    var url = namespaceManager.LookupNamespace(attribute.LocalName);

    if(url != null && url != attribute.Value)
    {
        namespaceManager.RemoveNamespace(attribute.LocalName, url);
        namespaceManager.AddNamespace(attribute.LocalName, attribute.Value);
    }
}


You don't need to do anything like this. Just use "my2" or something for the second namespace. You then need the new namespace prefix for any nodes that use the new namespace, and use the old "my" namespace prefix for all the nodes that still use the old namespace.

0

精彩评论

暂无评论...
验证码 换一张
取 消