ݺߣ

ݺߣShare a Scribd company logo
ObjectXPathNavigator – Как и зачем?

         Андрей Майоров. BYTE-force
Зачем нужен                              ?
                               (ObjectXPathNavigator)



•    Операции над графом объектов в памяти:
    – Перемещение по дереву. Любой объект в
       качестве корня.
    – Автоматически формируется дерево XML-узлов.
    – Выборки нужных объектов через XPath.
•    Граф объектов – в XSLT.
История
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).
Недостатки других решений
•  Невозможность управлять формой XML
  – Что идет в элементы?
  – А что в атрибуты?
  – С какими именами?
  – А неймспейсы какие?
•  Не расширяются снаружи
  – Как конвертировать значение в атрибут?
  – Специальная обработка нужного класса?
Еще есть XmlSerializer
•   Стандартней некуда.
•   Позволяет управлять формой.

•   НО сначала преобразует все в XML, и только потом
    отдает его приложению.
ObjectXPathNavigator
Использование #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 );
Использование #2
Регистрация специальной политики и конвертера

ObjectXPathContext context = new ObjectXPathContext( nsmgr );

context.RegisterNodePolicy(
    typeof( INullableType ),
    typeof( NullableNodePolicy ) );

context.ConverterFactory.AddConverter(
    typeof( NullableDateTime ),
    new NullableDateTimeConverter() );

XPathNavigator nav = context.CreateNavigator( o );
Разметка объектов
Разметка атрибутами:                               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; }
}
ObjectXPathNavigator
•   Центральный класс библиотеки.
•   Наследует у класса XPathNavigator.
•   Осуществляет движение по дереву узлов
    (элементов, атрибутов).
•   Дерево динамически создается по мере спуска по
    иерархии.
•   Умеет работать с «дочерними» навигаторами.
•   Узлы дерева хранятся в виде экземпляров класса
    Node.
Node
•   Аналогичен классу XmlNode.
•   «Отражает» реальный объект или связи между
    объектами.
•   Получение реального значения делается, когда это
    требуется *.

    * Есть тонкости.
NodePolicy
•   Политика отвечает за поведение узла иерархии.
•   Соответствует паттерну Policy (Strategy).
•   Упрощает расширение.
•   Позволяет менять поведение узлов на ходу.
Стандартные политики
• GenericNodePolicy
  Преобразует свойства обычного объекта в элементы
  и атрибуты.
• MemberNodePolicy
  Обслуживает узлы, значение которых еще не
  уточнялось навигатором.
• TextNodePolicy
  Для узлов типа «элемент», относящихся к полям с
  «простыми» значениями.
• ListNodePolicy
  Позволяет перемещаться по содержимому объектов,
  реализующих интерфейс IList.
Конвертеры
• В XML некоторые части графа объектов показаны в
  виде простого текста.
• Конвертеры преобразуют значения полей в текст.
• Можно писать новые конвертеры и регистрировать их

Некоторые стандартные конвертеры
• GenericConverter – просто использует ToString().
• BooleanConverter, DateTimeConverter,
  DoubleConverter и т.п. – форматируют результат в тот
  формат, который принят для XML.
• EnumConverter – преобразует значение в название.
Прозрачные узлы?
Берем класс                … получим 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>
Прозрачные узлы!
• Прозрачный узел – способ управления формой XML.
• Навигатор не останавливается на прозрачном узле
• Сделать узел прозрачным:
   • Атрибут [Transparent(true)].
   • Метод INodePolicy.GetIsTransparent().
• Некоторые узлы делаются прозрачными для
  соответствия правилам класса XmlSerializer*.

  * Следуем пока не всем правилам.
Добавление своих политик
• Реализуем интерфейс INodePolicy.
• Методы самоочевидны.
• В классе нужен метод GetPolicy().
             public static new INodePolicy GetPolicy()


Регистрация политики
• Атрибут NodePolicy на свойстве или классе.
• Метод RegisterNodePolicy (тип объекта, тип политики).
    – Тип объекта может быть интерфейсом.
• Событие NodePolicyGet.
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 );
}
Свои конвертеры

• Реализует интерфейс IConverter.
• ToString - преобразует значение объекта в текст.
• ParseString в данной версии не используется.
Регистрация конвертера
• Атрибут Converter на свойстве или классе.
• Используя метод AddConverter.

                         public interface IConverter
                         {
                           string ToString( object obj );
                           object ParseString( string str );
                         }
Возможные улучшения

• Полная совместимость со стандартным
  сериализатором.
• Оптимизация чтения данных.
• Обновление данных через навигатор.
• Типизированные элементы и атрибуты.
• Предотвращение зацикливания.
• и т.д.
Заключение

• Лицензия MIT-style.
• Текущая версия на нашем сайте:
  http://blogs.byte-force.com/files/12/objectxpathnavigator/default.aspx


• Free as in beer:

More Related Content

ObjectXPathNavigator - как и зачем?

  • 1. ObjectXPathNavigator – Как и зачем? Андрей Майоров. BYTE-force
  • 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: