2. Зачем нужен ?
(ObjectXPathNavigator)
• Операции над графом объектов в памяти:
– Перемещение по дереву. Любой объект в
качестве корня.
– Автоматически формируется дерево XML-узлов.
– Выборки нужных объектов через XPath.
• Граф объектов – в XSLT.
3. История
XPath Querying Over Objects with ОbjectXPathNavigator
• Статья в MSDN March 2003. Steve Saxon, Dell
Computer Corporation.
JXPath
• Простой интерпретатор XPath; может быть
применен к обычным графам объектов.
• Позволяет выполнять XPath-запросы и получать
итераторы.
XPathObjectNavigator в Bamboo.Prevalence
• Версия Java-библиотека Prevayler для .NET.
• Содержит XPathObjectNavigator (аналог JXPath).
4. Недостатки других решений
• Невозможность управлять формой XML
– Что идет в элементы?
– А что в атрибуты?
– С какими именами?
– А неймспейсы какие?
• Не расширяются снаружи
– Как конвертировать значение в атрибут?
– Специальная обработка нужного класса?
5. Еще есть XmlSerializer
• Стандартней некуда.
• Позволяет управлять формой.
• НО сначала преобразует все в XML, и только потом
отдает его приложению.
7. Использование #1
Простейшее использование
var context = new ObjectXPathContext();
var nav = context.CreateNavigator( o );
Регистрация неймспейса
var ctx = new ObjectXPathContext( nsmgr );
ctx.NamespaceManager.AddNamespace( quot;sdfquot;, “…” );
var nav = ctx.CreateNavigator( o );
8. Использование #2
Регистрация специальной политики и конвертера
ObjectXPathContext context = new ObjectXPathContext( nsmgr );
context.RegisterNodePolicy(
typeof( INullableType ),
typeof( NullableNodePolicy ) );
context.ConverterFactory.AddConverter(
typeof( NullableDateTime ),
new NullableDateTimeConverter() );
XPathNavigator nav = context.CreateNavigator( o );
9. Разметка объектов
Разметка атрибутами: XML:
[XmlRoot( quot;productquot;, Namespace=Namespaces.SDF )] <sdf:product
public class Product
{
id=quot;123quot;
[XmlAttribute( quot;idquot; )] name=quot;Red buttonquot;
public int ProductId{ get; set; } xmlns:sdf=quot;...quot;>
[XmlAttribute( quot;namequot; )]
public string Field1{ get; set; } <sdf:description>
Red button description
[XmlElement( quot;descriptionquot; )] </sdf:description>
public string Description{ get; set ; }
[XmlElement( quot;Datequot;, <Date>10.10.2006</Date>
Form=XmlSchemaForm.Unqualified )] ...
[Converter( typeof( SimpleConverter ))]
public DateTime Date{ get; set ; }
</sdf:product>
[XmlAnyElement]
public XmlElement Xml{ get; set; }
}
10. ObjectXPathNavigator
• Центральный класс библиотеки.
• Наследует у класса XPathNavigator.
• Осуществляет движение по дереву узлов
(элементов, атрибутов).
• Дерево динамически создается по мере спуска по
иерархии.
• Умеет работать с «дочерними» навигаторами.
• Узлы дерева хранятся в виде экземпляров класса
Node.
11. Node
• Аналогичен классу XmlNode.
• «Отражает» реальный объект или связи между
объектами.
• Получение реального значения делается, когда это
требуется *.
* Есть тонкости.
12. NodePolicy
• Политика отвечает за поведение узла иерархии.
• Соответствует паттерну Policy (Strategy).
• Упрощает расширение.
• Позволяет менять поведение узлов на ходу.
13. Стандартные политики
• GenericNodePolicy
Преобразует свойства обычного объекта в элементы
и атрибуты.
• MemberNodePolicy
Обслуживает узлы, значение которых еще не
уточнялось навигатором.
• TextNodePolicy
Для узлов типа «элемент», относящихся к полям с
«простыми» значениями.
• ListNodePolicy
Позволяет перемещаться по содержимому объектов,
реализующих интерфейс IList.
14. Конвертеры
• В XML некоторые части графа объектов показаны в
виде простого текста.
• Конвертеры преобразуют значения полей в текст.
• Можно писать новые конвертеры и регистрировать их
Некоторые стандартные конвертеры
• GenericConverter – просто использует ToString().
• BooleanConverter, DateTimeConverter,
DoubleConverter и т.п. – форматируют результат в тот
формат, который принят для XML.
• EnumConverter – преобразует значение в название.
15. Прозрачные узлы?
Берем класс … получим XML:
public class Person { <Person>
public string Name; <Name>John Smith</Name>
public string[] Alias; <Alias>
} <string>Johnny</string>
<string>Smithy</string>
</Alias>
А хотелось-то получить: </Person>
<person>
<name>John Smith</name>
<alias>Johnny</alias>
<alias>Smithy</alias>
</person>
16. Прозрачные узлы!
• Прозрачный узел – способ управления формой XML.
• Навигатор не останавливается на прозрачном узле
• Сделать узел прозрачным:
• Атрибут [Transparent(true)].
• Метод INodePolicy.GetIsTransparent().
• Некоторые узлы делаются прозрачными для
соответствия правилам класса XmlSerializer*.
* Следуем пока не всем правилам.
17. Добавление своих политик
• Реализуем интерфейс INodePolicy.
• Методы самоочевидны.
• В классе нужен метод GetPolicy().
public static new INodePolicy GetPolicy()
Регистрация политики
• Атрибут NodePolicy на свойстве или классе.
• Метод RegisterNodePolicy (тип объекта, тип политики).
– Тип объекта может быть интерфейсом.
• Событие NodePolicyGet.
18. INodePolicy
При смене объекта
public interface INodePolicy
{
INodePolicy GetNewPolicy( Node node );
string GetName( Node node );
string GetNamespace( Node node );
XPathNodeType GetNodeType( Node node );
string GetValue( Node node );
bool GetIsTransparent( Node node );
int GetAttributesCount( Node node );
Node GetAttribute( Node node, int index );
int FindAttribute( Node node, string name, string ns );
int GetChildrenCount( Node node );
Node GetChild( Node node, int index );
}
19. Свои конвертеры
• Реализует интерфейс IConverter.
• ToString - преобразует значение объекта в текст.
• ParseString в данной версии не используется.
Регистрация конвертера
• Атрибут Converter на свойстве или классе.
• Используя метод AddConverter.
public interface IConverter
{
string ToString( object obj );
object ParseString( string str );
}
20. Возможные улучшения
• Полная совместимость со стандартным
сериализатором.
• Оптимизация чтения данных.
• Обновление данных через навигатор.
• Типизированные элементы и атрибуты.
• Предотвращение зацикливания.
• и т.д.
21. Заключение
• Лицензия MIT-style.
• Текущая версия на нашем сайте:
http://blogs.byte-force.com/files/12/objectxpathnavigator/default.aspx
• Free as in beer: