В данной статье хотелось бы рассказать о проблеме, решение которой я не сразу понял, потому что такое исключение нигде не встречалось в интернете.
Работая с XPathNavigator, XPathDocument (возможно и с XDocument) и используя свой класс XsltContext (подкласс XmlNamespaceManager) контекст, что бы писать свои функции для XPath, можно словить исключение:
System.NullReferenceException "Object reference not set to an instance of an object."Причина:
at MS.Internal.Xml.XPath.BaseAxisQuery.matches(XPathNavigator e)
at MS.Internal.Xml.XPath.CacheChildrenQuery.Advance()
at MS.Internal.Xml.XPath.AttributeQuery.Advance()
at MS.Internal.Xml.XPath.LogicalExpr.cmpQueryQueryE(Op op, Object val1, Object val2)
at MS.Internal.Xml.XPath.LogicalExpr.Evaluate(XPathNodeIterator nodeIterator)
at MS.Internal.Xml.XPath.FilterQuery.EvaluatePredicate()
at MS.Internal.Xml.XPath.FilterQuery.Advance()
at MS.Internal.Xml.XPath.CacheChildrenQuery.GetNextInput()
at MS.Internal.Xml.XPath.CacheChildrenQuery.Advance()
at MS.Internal.Xml.XPath.CacheChildrenQuery.GetNextInput()
at MS.Internal.Xml.XPath.CacheChildrenQuery.Advance()
at MS.Internal.Xml.XPath.XPathSelectionIterator.MoveNext()
При использовании своей реализации XsltContext пропадает проверка на наличие добавленного namespace (через AddNamespace) у контекст менеджера. В результате, казалось бы обычный XPath запрос перестаёт ругаться на неизвестное пространство имен исключениями формата "XPathException. Additional information: Namespace prefix 'myns1' is not defined." и просто сваливается с NullReferenceException без какой либо причины.Решение:
Добавить в XmlNamespaceManager namespace из XPath запроса.
Демонстрация:
Для наглядности приведу код, который будет падать с этой ошибкой. Если в нем раскомментировать "// Error fix" строку, тогда ошибка пропадёт.
static void Main(string[] args) { var xml = @"<?xml version=""1.0"" encoding=""utf-8""?> <root xmlns:myns1=""http://mynamespace1.com/format#""> <MyText>Text1</MyText> <myns1:MyNamespace>Value1</myns1:MyNamespace> </root>"; // Загружаем XML var document = new XPathDocument(new StringReader(xml)); // Создаем навигатор для работы var navigator = document.CreateNavigator().SelectSingleNode("//MyText"); // Используем свой контекст менеджер var manager = new XmlNamespaceManager(new NameTable()); // Error fix (раскомментить) //manager.AddNamespace("myns1", "http://mynamespace1.com/format#"); // Запрос var allNodes = navigator.Select("//*[myns1:MyNamespace/text() = 'Value1']", manager); // Exception here if (allNodes.MoveNext()) { } } private class TestXsltContext : XsltContext { public TestXsltContext(NameTable table) : base(table) { } public override IXsltContextVariable ResolveVariable(string prefix, string name) { throw new NotImplementedException(); } public override IXsltContextFunction ResolveFunction(string prefix, string name, XPathResultType[] ArgTypes) { throw new NotImplementedException(); } public override bool PreserveWhitespace(XPathNavigator node) { throw new NotImplementedException(); } public override int CompareDocument(string baseUri, string nextbaseUri) { throw new NotImplementedException(); } public override bool Whitespace { get; } }
.
Комментариев нет:
Отправить комментарий