XML   Magic упрощаем сериализацию E-mail: khotin@gmx.com Игорь Хотинь
Background <ul><li>11+ лет в IT-индустрии
6+ лет с Java
Сторонник гибкого дизайна </li></ul><ul><li>Agile-практик </li></ul>
Source of the problem <ul><li>Ингридиенты для шаманства </li></ul>
public   class  CodeSource { List<CustomError>  errorList =  new  ArrayList<CustomError>(); public  CodeSource() { // fill...
public   class  CustomError { private   int   code ; private  String  message ; public  String toString() { return   &quot...
public   class  Source { private   int   problem ; public   void  setProblem( int  problem) { this . problem  = problem; }...
Source of the problem <ul><li>Константы в коде
Data-driven approach
XML </li></ul>
Почему XML? <ul><li>Стандарт
Доступные средства парсинга и верификации
Self-describing (в определённой степени)
Human-readable (в определённой степени)
Сложный, многословный, перегруженный
Алтернатива: JSON, YAML, SDL... </li></ul>
XML в нашей индустрии: всерьёз и надолго
< config > < handler >   < error >   < code > 101 </ code >   < message > Not our fault </ message >   </ error >   < erro...
XML Binding <ul><li>XML -> Java Beans -> XML
Лёгкий для понимания
Минимум кода, быстрая реализация
Гибкий </li></ul>
SAX - Simple API for XML <ul><li>Event-driven parsing
Максимум скорости
Минимум памяти
Сложность в обработке сложных структур
Read-only </li></ul>
List<CustomError>  errorList  =  new  ArrayList<CustomError>(); Source  source  =  new  Source(); public  SaxSource(InputS...
String  tempVal ; CustomError  tempError ; public   void  startElement(String uri, String localName, String qName, Attribu...
DOM – Document Object Model <ul><li>Универсальная модель
XML-дерево
Ресурсоёмко
Boilerplate-код
No Java-feel </li></ul>
List<CustomError>  errorList  =  new  ArrayList<CustomError>(); Source  source  =  new  Source(); public  DomSource(InputS...
nl = root.getElementsByTagName( &quot;source&quot; ); if  (nl !=  null  && nl.getLength() > 0) { Element src = (Element)nl...
DOM + Xpath <ul><li>Гибкая выборка нужных данных
Ресурсоёмко
Upcoming SlideShare
Loading in …5
×

XML Magic

1,206 views

Published on

Tools to simplify XML serialization

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,206
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

XML Magic

  1. 1. XML Magic упрощаем сериализацию E-mail: khotin@gmx.com Игорь Хотинь
  2. 2. Background <ul><li>11+ лет в IT-индустрии
  3. 3. 6+ лет с Java
  4. 4. Сторонник гибкого дизайна </li></ul><ul><li>Agile-практик </li></ul>
  5. 5. Source of the problem <ul><li>Ингридиенты для шаманства </li></ul>
  6. 6. public class CodeSource { List<CustomError> errorList = new ArrayList<CustomError>(); public CodeSource() { // fill the error list CustomError error = new CustomError(); error.setCode(101); error.setMessage( &quot;Is there an error in this code?&quot; ); errorList .add(error); // create the source Source source = new Source(); source.setProblem(101); // raise an error source.error( errorList ); } }
  7. 7. public class CustomError { private int code ; private String message ; public String toString() { return &quot;Error #&quot; + code + &quot;: &quot; + message ; } public int getCode() { return this . code ; } public void setCode( int code) { this . code = code; } public void setMessage(String message) { this . message = message; } }
  8. 8. public class Source { private int problem ; public void setProblem( int problem) { this . problem = problem; } public void error(List<CustomError> errorList) { for (CustomError e: errorList) { if (e.getCode() == this . problem ) { System. err .println(e); return ; } } System. err .println( &quot;Error: error not found&quot; ); } }
  9. 9. Source of the problem <ul><li>Константы в коде
  10. 10. Data-driven approach
  11. 11. XML </li></ul>
  12. 12. Почему XML? <ul><li>Стандарт
  13. 13. Доступные средства парсинга и верификации
  14. 14. Self-describing (в определённой степени)
  15. 15. Human-readable (в определённой степени)
  16. 16. Сложный, многословный, перегруженный
  17. 17. Алтернатива: JSON, YAML, SDL... </li></ul>
  18. 18. XML в нашей индустрии: всерьёз и надолго
  19. 19. < config > < handler > < error > < code > 101 </ code > < message > Not our fault </ message > </ error > < error > < code > 102 </ code > < message > Keyboard not found... press F1 to continue </ message > </ error > < error > < code > 103 </ code > < message > Reserved for future mistakes by our developers </ message > </ error > </ handler > < source > < problem > 102 </ problem > </ source > </ config >
  20. 20. XML Binding <ul><li>XML -> Java Beans -> XML
  21. 21. Лёгкий для понимания
  22. 22. Минимум кода, быстрая реализация
  23. 23. Гибкий </li></ul>
  24. 24. SAX - Simple API for XML <ul><li>Event-driven parsing
  25. 25. Максимум скорости
  26. 26. Минимум памяти
  27. 27. Сложность в обработке сложных структур
  28. 28. Read-only </li></ul>
  29. 29. List<CustomError> errorList = new ArrayList<CustomError>(); Source source = new Source(); public SaxSource(InputStream input) { try { SAXParserFactory factory = SAXParserFactory. newInstance (); SAXParser saxParser = factory.newSAXParser(); saxParser.parse(input, this ); source .error( errorList ); } catch (Throwable e) { e.printStackTrace(); } }
  30. 30. String tempVal ; CustomError tempError ; public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { tempVal = &quot;&quot; ; if (qName.equalsIgnoreCase( &quot;error&quot; )) { tempError = new CustomError(); } } public void characters( char [] ch, int start, int length) throws SAXException { tempVal += new String(ch, start, length); } public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equalsIgnoreCase( &quot;error&quot; )) { errorList .add( tempError ); } else if (qName.equalsIgnoreCase( &quot;message&quot; )) { tempError .setMessage( tempVal ); } else if (qName.equalsIgnoreCase( &quot;code&quot; )) { tempError .setCode(Integer. parseInt ( tempVal .trim())); } else if (qName.equalsIgnoreCase( &quot;problem&quot; )) { source .setProblem(Integer. parseInt ( tempVal .trim())); } }
  31. 31. DOM – Document Object Model <ul><li>Универсальная модель
  32. 32. XML-дерево
  33. 33. Ресурсоёмко
  34. 34. Boilerplate-код
  35. 35. No Java-feel </li></ul>
  36. 36. List<CustomError> errorList = new ArrayList<CustomError>(); Source source = new Source(); public DomSource(InputStream input) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory. newInstance (); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(input); Element root = doc.getDocumentElement(); NodeList nl = root.getElementsByTagName( &quot;handler&quot; ); if (nl != null && nl.getLength() > 0) { Element e = (Element)nl.item(0); NodeList errList = e.getElementsByTagName( &quot;error&quot; ); for ( int i = 0; i < errList.getLength(); i++) { CustomError error = new CustomError(); Element el = (Element)errList.item(i); if (el == null ) continue ; NodeList clist = el.getElementsByTagName( &quot;code&quot; ); if (clist != null && clist.getLength() > 0) { error.setCode(Integer. parseInt ( clist.item(0).getTextContent())); } NodeList mlist = el.getElementsByTagName( &quot;message&quot; ); if (mlist != null && mlist.getLength() > 0) { error.setMessage(mlist.item(0).getTextContent()); } this . errorList .add(error); } } дурDOM
  37. 37. nl = root.getElementsByTagName( &quot;source&quot; ); if (nl != null && nl.getLength() > 0) { Element src = (Element)nl.item(0); NodeList plist = src.getElementsByTagName( &quot;problem&quot; ); if (plist != null && plist.getLength() > 0) { this . source .setProblem(Integer. parseInt (plist.item(0) .getTextContent())); } } XMLSerializer serializer = new XMLSerializer(); serializer.setOutputCharStream( new java.io.FileWriter( &quot;out.xml&quot; )); serializer.serialize(doc); } catch (Exception e) { e.printStackTrace(); } source .error( errorList ); }
  38. 38. DOM + Xpath <ul><li>Гибкая выборка нужных данных
  39. 39. Ресурсоёмко
  40. 40. Boilerplate-код
  41. 41. No Java-feel </li></ul>
  42. 42. List<CustomError> errorList = new ArrayList<CustomError>(); Source source = new Source(); public XPathSource(InputStream input) { try { XPath xpath = XPathFactory. newInstance ().newXPath(); DocumentBuilderFactory dbf = DocumentBuilderFactory. newInstance (); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(input); Element root = doc.getDocumentElement(); NodeList nl = (NodeList)xpath.evaluate( &quot;handler/error/code/text()&quot; , root, XPathConstants. NODESET ); for ( int i = 0; i < nl.getLength(); i++) { CustomError error = new CustomError(); error.setCode(Integer. parseInt (nl.item(i).getTextContent())); errorList .add(error); } nl = (NodeList)xpath.evaluate( &quot;handler/error/message/text()&quot; , root, XPathConstants. NODESET ); for ( int i = 0; i < nl.getLength(); i++) { errorList .get(i).setMessage(nl.item(i).getTextContent()); } Double problem = (Double)xpath.evaluate( &quot;source/problem&quot; , root, XPathConstants. NUMBER ); source .setProblem(problem.intValue()); source .error( errorList ); } catch (Exception e) { e.printStackTrace(); } }
  43. 43. JDOM <ul><li>Java-ориентированная XML-модель
  44. 44. Интеграция с SAX и DOM
  45. 45. Поддерживает XPath и XSLT
  46. 46. Заброшенный JSR 102
  47. 47. Меньше Boilerplate, чем DOM
  48. 48. Java-feel API </li></ul>
  49. 49. List<CustomError> errorList = new ArrayList<CustomError>(); Source source = new Source(); public JdomSource(InputStream input) { try { SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(input); Element root = doc.getRootElement(); Element handler = root.getChild( &quot;handler&quot; ); List elist = handler.getChildren( &quot;error&quot; ); for (Object obj: elist) { CustomError error = new CustomError(); Element err = (Element)obj; error.setCode(Integer. parseInt (err.getChildTextTrim( &quot;code&quot; ))); error.setMessage(err.getChildText( &quot;message&quot; )); errorList .add(error); } Element source = root.getChild( &quot;source&quot; ); this . source .setProblem( Integer. parseInt (source.getChildTextTrim( &quot;problem&quot; ))); XMLOutputter outp = new XMLOutputter(); outp.output(doc, new FileOutputStream( &quot;jdom.xml&quot; )); } catch (Exception e) { e.printStackTrace(); } source .error( errorList ); }
  50. 50. Другие способы? <ul><li>StAX – Streaming API for XML?
  51. 51. XStream?
  52. 52. JAXB (JSR 222)?
  53. 53. Apache XMLBeans?
  54. 54. JiBX?
  55. 55. Hibernate 3 XML Mapping(!) ?
  56. 56. ... </li></ul>
  57. 57. Apache Digester
  58. 58. Apache Digester <ul><li>Призван упростить парсинг конфигураций
  59. 59. Rule-based parsing engine
  60. 60. В основе – стек
  61. 61. По заданным правилам digester: </li><ul><li>Создаёт объекты на вершине стека
  62. 62. Присваивает объектам свойства
  63. 63. Связывает их друг с другом </li></ul></ul>
  64. 64. List<CustomError> errorList = new ArrayList<CustomError>(); Source source = new Source(); public DigesterSource(InputStream input) { try { Digester digester = new Digester(); digester.addObjectCreate( &quot;config/handler/error&quot; , CustomError. class ); digester.addBeanPropertySetter( &quot;config/handler/error/code&quot; , &quot;code&quot; ); digester.addBeanPropertySetter( &quot;config/handler/error/message&quot; , &quot;message&quot; ); digester.addSetNext( &quot;config/handler/error&quot; , &quot;addError&quot; ); digester.addObjectCreate( &quot;config/source&quot; , Source. class ); digester.addBeanPropertySetter( &quot;config/source/problem&quot; , &quot;problem&quot; ); digester.addSetNext( &quot;config/source&quot; , &quot;setSource&quot; ); digester.push( this ); digester.parse(input); this . source .error( this . errorList ); } catch (Exception e) { e.printStackTrace(); } } public void addError(CustomError error) { this . errorList .add(error); } public void setSource(Source source) { this . source = source; }
  65. 65. Apache Digester <ul><li>Гибкость
  66. 66. Reflection – влияет на производительность
  67. 67. Read-only </li></ul>
  68. 68. Apache Digester <ul><li>Широкий выбор правил: </li><ul><li>ObjectCreateRule
  69. 69. FactoryCreateRule
  70. 70. SetPropertiesRule
  71. 71. SetNextRule
  72. 72. CallMethodRule
  73. 73. ... </li></ul><li>Custom rules
  74. 74. XML and @nnotation конфигурации </li></ul>
  75. 75. Simple <ul>high performance XML serialization and configuration framework </ul>
  76. 76. Simple <ul><li>Подход, основанный на метаданных
  77. 77. Простой фреймворк с широкими возможностями
  78. 78. Zero-configuration
  79. 79. Rapid Development
  80. 80. Human-readable XML </li></ul>
  81. 81. public SimpleSource(InputStream input) { try { Serializer serializer = new Persister(); Config config = (Config)serializer .read(Config. class , input); config.error(); serializer.write( config, new File(&quot;simple.xml&quot;)); } catch (Exception e) { e.printStackTrace(); } }
  82. 82. @Root (name= &quot;config&quot; ) public class Config { @ElementList (name= &quot;handler&quot; ) private List<CustomError> list ; @Element private Source source ; public void error() { this . source .error( list ); } }
  83. 83. public class CustomError { @Element private int code ; @Element private String message ; public String toString() { return &quot;Error #&quot; + code + &quot;: &quot; + message ; } public int getCode() { return this . code ; } public void setCode( int code) { this . code = code; } public void setMessage(String message) { this . message = message; } }
  84. 84. public class Source { @Element private int problem ; public void setProblem( int problem) { this . problem = problem; } public void error(List<CustomError> errorList) { for (CustomError e: errorList) { if (e.getCode() == this . problem ) { System. err .println(e); return ; } } System. err .println( &quot;Error: error not found&quot; ); } }
  85. 85. Simple <ul><li>Настолько просто, что не о чем рассказывать – достаточно трёх аннотаций :) </li><ul><li>@Root
  86. 86. @Element
  87. 87. @Attribute </li></ul><li>Маппинг за 5 минут
  88. 88. Замечательный туториал </li></ul>
  89. 89. Simple , но если нужно что-то более сложное... <ul><li>Перехватчики процесса сериализации
  90. 90. Конвертеры для ручной сериализации
  91. 91. Маппинг XPath выражений
  92. 92. Поддержка версионности </li></ul>
  93. 93. А что выбираешь ты?
  94. 95. Ресурсы <ul><li>simple.sourceforge.net
  95. 96. commons.apache.org/digester
  96. 97. www.jdom.org
  97. 98. www.w3.org/DOM
  98. 99. www.w3.org/TR/xpath </li></ul>
  99. 100. Контакты E-mail: [email_address] Blog: www.ikhotin.com Twitter: chaostarter linkedin .com/pub/igor-khotin/5/193/257

×