26 марта 2018 г.

Функции current() if-else() и string.Format() XPath выражений для XPathNavigator (XPathDocument).

Скачать проект с примерами ниже можно по ссылке:

https://bitbucket.org/sergey_vaulin/xpathfunctions/src


Предыстория.


На работе появилась потребность реализовать механизм, который бы давал возможность из XML извлекать нужные данные и на их основе создавать бизнес объекты, а затем передавать их на обработку в другую систему. При этом поля требовалось забирать не просто в рамках одного узла, а сам XML представлял из себя дерево, а значит каждый узел имел ссылку на родителя, и надо было ездить по всему дерево обрабатывая узлы в зависимости от их типа. Решение было использовать XPath выражения, но оказалось не все так просто.

Подводные камни.


Для комфортного извлечения данных из XML нам требовалась поддержка XPath 2.0 (https://www.w3.org/TR/xquery-operators/) выражений и функций, которая, судя по msdn, должна быть в XPathNavigator. Но на практике оказалось, что большая часть функций попросту отсутствует и доступны только методы XPath 1.0.

Недостатки XPathNavigator.


  • Список функций представлен в internal class XPathParser который находится в System.Xml.dll (так же стоит отметить, что поддерживаются функция node(), text(), processing-instruction(), comment())

13 марта 2018 г.

XPathNavigator ошибка при парсе.


В данной статье хотелось бы рассказать о проблеме, решение которой я не сразу понял, потому что такое исключение нигде не встречалось в интернете.

Работая с 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 без какой либо причины.

8 марта 2018 г.

Классическая игра сапер (Minesweeper). Клон на С#,WPF

Все игры:


Скачать исходный код можно по ссылке:


В данной статье я расскажу о написании аналога классического "Сапера", который идёт стандартной игрой в Windows начиная с Windows XP. Англоязычное название этой игры звучит как Minesweeper. Про алгоритм можно подробно почитать на Wiki_(Сапер). Начиная с Windows 10 при установке операционной системы с нуля, игру, без предварительной загрузки из магазина, не найти, да и визуально скачанный сапер будет отличаться от классического, к которому лично я так привык. Поэтому скачать классического сапера по ссылке Minesweeper с так знакомыми глазу изображениями кнопок и вспомнить молодость :) Либо скомпилировать и запустить мой проект, в котором использованы изображения из классического сапера. Проект выполнен на языку C#, а визуальный интерфейс на WPF.

Предварительный просмотр оригинала и клона: