XML і Java: Три підходи до збереження XML (исходники), Різне, Програмування, статті

XML-дані треба десь зберігати


XML – чудовий формат представлення даних, що підтверджується і наявністю цілого розділу, присвяченого XML, на сайті IBM developerWorks. В наші дні обговорення XML найчастіше проходить в контексті Web-сервісів, перетворень Java ™-об’єктів в XML і назад, і навіть використання баз даних XML замість реляційних або об’єктно-орієнтованих.


У той же час мало кого цікавить, яким чином XML-документи, представлені в пам’яті за допомогою DOM, JDOM або чогось ще, перетворюються у файли на диску, повні кутових дужок і лапок. Чесно кажучи, запис XML в файл – це не саме захоплююче заняття, але від нього нікуди не подітися. Ви тільки спробуйте уявити собі ситуацію, при якій неможливо зберегти XML-документ в файл! Ви можете створювати XML-документи в пам’яті і пересилати їх між різними модулями вашого застосування (а може навіть між кількома додатками), будучи не в змозі зберегти де-небудь дані. Наприклад, можна створювати документи для подання конфігурацій, розробивши всілякі корисні утиліти для їх читання, при цьому не маючи можливості їх зберегти. Або ж можна прочитати повідомлення SOAP, але не можна записати його в файл у випадку втрати з’єднання з мережею.


Таким чином, важливість запису файлів XML абсолютно очевидна. Більше того, якби нікого не хвилювали питання тривалого збереження даних, а єдине, що було б потрібно – це всього лише перетворювати їх у пам’яті, то цілком можливо, що в XML просто не було б необхідності, і вже у всякому разі, він не був би настільки важливий, як в наші дні.


При цьому залишається просте запитання: а як краще зберігати XML-дані в файл? Ця стаття в основному розрахована на програмістів, яким доводиться цим займатися. При цьому якщо ви взагалі не стикалися з такою необхідністю, то стаття також буде корисна, тому що ви навчитеся це робити. Для тих же з вас, хто займається збереженням даних, я вирішив розглянути три основні підходи:



  1. Використання DOM, JDOM API і їм подібних технологій для запису у файл безпосередньо зі структур даних XML в пам’яті.
  2. Використання TrAX (Transformation API for XML) і тотожного перетворення для збереження XML-даних.
  3. Використання високоуровнего API, такого як JAXB.

Збереження безпосередньо через API


Якщо читання XML-даних здійснюється за допомогою одного або декількох API, то цілком логічно і зберігати XML-документ, використовуючи ті ж API. Наприклад, при роботі з XML через JDOM API після отримання посилання на об’єкт JDOM Document запис можна здійснювати таким чином:






XMLOutputter outputter = new XMLOutputter();
outputter.setFormat(Format.getPrettyFormat());
outputter.output(myDocument, new FileWriter(“outputFile.xml”));

Схожим чином можна записувати XML, використовуючи новий API для завантаження і збереження в специфікації DOM Level 3:






DOMWriter writer = new org.apache.xml.serialize.XMLSerializer();
writer.setNewLine(”
“);
writer.setEncoding(“UTF-8”);
writer.writeNode(new FileOutputStream(new File(“outputFile.xml”)), myDocument);

Новий DOM API можна використовувати безліччю різних способів. При цьому якісь із них сильніше прив’язані до конкретної реалізації DOM API, наприклад, як вищенаведений клас, який використовує Xerces. Хоча є й інші способи, які не залежать від конкретних бібліотек, вони не настільки наочні для демонстрації.


Переваги


Перевагою збереження через API є те, що ви працюєте безпосередньо з API і, отже, тримайте все під контролем. Наприклад, ви можете додавати нові рядки, вказувати відступи і т.д., аж до найдрібніших деталей. При цьому мало, що відокремлює вас від безпосереднього доступу до файлу: немає ні обгорток API, ні будь-яких абстрактних шарів, так що ви можете працювати з XML на дуже низькому рівні. Так що якщо ви впевнено володієте JDOM або DOM, то використання цих API – дуже зручний спосіб збереження XML-даних.


Недоліки


Недоліки прямого збереження через API найчастіше є зворотною стороною переваг. Через те, що практично всі аспекти виведення знаходяться під контролем програміста, неправильне використання API легко може привести до невірного збереження даних. Наприклад, поширеними помилками є неправильні переклади рядків, невірна кодування, а також помилки вводу-виводу. При цьому доводиться працювати на дуже низькому рівні, практично без допомоги будь-яких допоміжних утиліт (JDOM надає тільки методи Format.getPrettyFormat() і Format.getCompactFormat(), А DOM – і того менше). Таким чином, необхідно досконально знати кодування, формати запису, правила відступів і інші аспекти, які мають будь-яке значення для збереження файлу.


Формати перетворення


Одна з популярних альтернатив – це використання TrAX і тотожного перетворення. TrAX – це API для XML-перетворень (Transformation API for XML). В даний час TrAX є частиною JAXP, яка включаються практично в усі релізи Java (крім Micro Edition). TrAX дозволяє використовувати таблиці стилів XSL для перетворення XML-документів. TrAX надає можливість перетворення SAX-подій або DOM-документів в XML-файли і назад, що зручно, тому що SAX і DOM є найбільш поширеними методами роботи з XML. Наприклад, можна взяти DOM-документ, перетворити його за допомогою TrAX і зберегти результат у файлі. Або ж можна вважати файл, перетворити його і представити у вигляді DOM Document.


В окремому випадку можна використовувати таблицю стилів, не задающую ніякого перетворення даних, і використовувати її для перекладу документа з одного формату в іншій. Використання такої таблиці стилів, яка просто дублює вхідний документ, називається тотожним перетворенням. Таким чином, можна вважати документ з файлу, застосувати тотожне перетворення і отримати той же самий документ у вигляді DOM. Зворотна дія-з DOM в файл-є нічим іншим, як збереженням XML. Це робиться приблизно так:






Source domSource = new DOMSource(myDOMDocument);
Result fileResult = new StreamResult(new File(“outputFile.xml”));
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(domSource, fileResult);

У цьому прикладі DOM-документ зберігається в XML-файлі outputFile.xml.


Переваги TrAX


Найбільшим плюсом TrAX є простота використання. TrAX легко викликається з Java-коду і не вимагає серйозних знань SAX або DOM, що робить його дуже привабливим для програмістів, що не володіють впевненими навичками роботи з XML. До того ж, його можуть використовувати початківці програмісти, незнайомі з SAX або DOM, т.к. достатньо вивчити 10-20 рядків коду і можна зберігати XML-дані в файл або перетворювати в DOM-документи та набори SAX-подій.


Зворотний бік використання TrAX


Найбільшим недоліком TrAX є те, що при всій простоті перетворень, досить важко контролювати дрібні деталі виводу, такі як переклади рядків, кодування, прогалини і відступи. TrAX підтримує роботу з цими аспектами збереження, але це далеко не так просто, як у випадку безпосереднього використання DOM або JDOM. Як правило, простота використання TrAX поєднується з браком гнучкості при збереженні в файл, принаймні, на перший погляд.


При цьому, практично все, що можна робити через DOM або JDOM, можна досягти і при використанні TrAX, але це не настільки просто і інтуїтивно. Доводиться вникати в деталі XSLT і TrAX API, які мають вельми слабке відношення до практичних завдань збереження XML.


Використання прив’язки до даних (data binding) для збереження XML


Ще одним способом перекладу XML в зріз-особливо, якщо це подання має бути у вигляді файлу на диску-є використання API для прив’язки до даних (data binding), таких як JAXB. Незважаючи на те, що прив’язка до даних, як правило, не розглядається як метод їх збереження, вона фактично є таким. Це не що інше, як спосіб взяти XML-документ в пам’яті і записати його у файл.


На жаль, через обмеженість обсягу статті, я не можу детально розповісти, що таке прив’язка до даних, але ви можете прочитати кілька статей на цю тему на сайті developerWorks. Нижче представлений фрагмент коду в стилі JAXB, який зберігає XML на диск:






FileOutputStream stream = new FileOutputStream(“outputFile.xml”);
Marshaller marshaller = myJaxbContext.createMarshaller();
marshaller.marshal(myJavaObject, stream);

Ви можете задавати різні параметри, такі як кодування вихідного файлу через об’єкт Marshaller. У сенсі гнучкості налаштування параметрів виводу, JAXB не сильно відрізняється від вищерозглянутих підходів.


Переваги JAXB


Одним з найбільш істотних переваг JAXB є простота використання, особливо при вирішенні нескладних завдань. До того ж, у той час як SAX і DOM вважаються досить складними у використанні (по Принаймні, у колі пересічних програмістів), розуміння JAXB необхідно практично кожному Java-розробнику. Як наслідок, викладено багато статей і керівництв по JAXB, що підтверджується оглядами публікацій на сайтах типу developerWork за 2007 рік. Крім цього, JAXB краще підтримується, ніж DOM або SAX. Незважаючи на те, що реалізації SAX і DOM також включені в релізи Java-платформи, JAXB є дітищем Sun Microsystems, так що його підтримка обіцяє бути краще.


Від вас не потрібно глибоких знань XML, щоб почати використовувати JAXB. Ви можете працювати з звичайними Java-об’єктами (а не специфічними інтерфейсами, типу Node або Text в DOM), а потім зберегти їх в XML. Як наслідок, вам не доведеться вивчати гору нового матеріалу, перед тим як почати працювати з JAXB, що особливо цінно, коли ваш бос вимагає від вас результатів негайно.


Недоліки JAXB


У той же час необов’язковість знання XML також є певним недоліком JAXB, тому що чим менше ви знаєте про XML, тим складніше розумно використовувати JAXB. У підсумку, може запросто вийти погано відформатований XML-документ або документ, в якому присутня тільки частина об’єктів, а, може, і зовсім не ті об’єкти, які повинні були бути збережені.


В результаті розробники часто змушені або взагалі відмовитися від використання JAXB, або починати глибше вивчати XML, SAX і DOM. Більш того, після цього багато хто з них просто переходять на використання SAX і DOM, залишаючи для JAXB лише найпростішу функцію конвертації між XML і Java-об’єктами.


І останній підхід …


Я свідомо обійшов увагою ще один варіант формування XML-файла, а саме: запис послідовності біт, байт і рядків безпосередньо в FileOutputStream або FileWriter. Це цілком здійсненно на практиці і іноді використовується. Проте в цьому випадку замість збереження XML-даних відбувається просто створення нового XML-документа на основі даних, представлених в будь-якому іншому форматі. Подібні дії легко розпізнати на практиці, тому як код, як правило, виглядає як на фрагменті нижче:






String xmlString = setupXMLBuffer(
new StringBuffer(“<firstName>”)
.append(customer.firstName)
.append(“</firstName>”)
.append(“<lastName>”)
.append(customer.lastName)
.append(“</lastName>”)
// etc…
.toString()
);
bufferedWriter.write(xmlString);
// other file I/O code

У такому підході немає нічого фундаментально неправильного, просто замість збереження XML-документа, відбувається збереження даних і одночасне наповнення ними XML-файла. Таким чином, питання збереження саме XML-документів в даному випадку виявляються несуттєвими, тому що неможливо відокремити збереження даних від переведення їх в XML.


Висновок


В цілому не існує єдино вірного підходу до збереження XML-документів, так що корисно обговорювати різні варіанти, використовувані різними Java і XML-розробниками. Головне, запитайте себе, є Чи ваш підхід до цієї загальної проблеми послідовним? Чи дозволяє він зберігати XML-документи на диску у вигляді, зручному для подальшого використання: читання, розуміння та обміну даними між додатками?


Таким чином, метою цієї статті було змусити людей більше спілкуватися на тему застосовності конкретних підходів у тих чи інших ситуаціях. Досвід інших розробників може виявитися дуже корисним при вирішенні вашої проблеми, так що не пошкодуйте часу на вивчення форумів з Java і XML.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*