Могу ли я создать объект XmlNamespaceManager из XML-файла, который я собираюсь прочитать? - PullRequest
4 голосов
/ 11 января 2011

У меня есть некоторый код c #, работающий на sharepoint, который я использую для проверки внутри xml документа infopath, чтобы узнать, должен ли я проверить документ или отказаться от документа.

Код работает нормально для парыразличных шаблонов форм, которые я создал, но у меня не получилось.Я обнаружил, что создаваемый мною XmlNamespaceManager содержит неверное определение для пространства имен 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");`

Затем я могу использовать следующую строку кода для поиска xml, который я получаю после

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

nav.Value, тогда получаются те данные, которые я хочу.

Это всеотлично работает на пару моих шаблонов форм.У меня есть новый шаблон формы, и я обнаружил, что вместо этого мне нужно использовать эту строку

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

Дата отличается.

Моя проблема в том, что я не могу добавить это дважды как только 1 комплектформ будет работать.

Так что мой вопрос.Есть ли способ, которым я могу сгенерировать объект NamespaceManager из файла XML, поскольку все это содержится в заголовке?Я не смог найти простой способ обойти это.

Ответы [ 3 ]

4 голосов
/ 10 февраля 2011

Я нашел способ сделать это. Вместо добавления «моего» пространства имен его можно извлечь из объекта XmlDocument. Это может быть просто немного удачи, что это работает таким образом, но я доволен этим.

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

formXML - это XmlDocument, созданный из инфопатического XML

1 голос
/ 11 января 2011

Один из вариантов - попытаться загрузить узел xml, используя первое пространство имен, если это не дает никаких результатов, вызвать PushScope (), переопределить определение первого пространства имен, выбрать и т. Д. ...

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();

Другим вариантом является анализ атрибутов в заголовке и поиск любых содержащихся им пространств имен

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);
    }
}
0 голосов
/ 11 января 2011

Вам не нужно делать ничего подобного. Просто используйте «my2» или что-то для второго пространства имен. Затем вам понадобится новый префикс пространства имен для любых узлов, которые используют новое пространство имен, и используйте старый префикс «my» для пространства имен для всех узлов, которые все еще используют старое пространство имен.

...