IBM®
Перейти к тексту
    в России и странах СНГ [изменить]    Условия использования
 
 
   
    Главная страница    Продукты    Услуги и решения    Поддержка и загрузка    Мой профиль    
Перейти к тексту

developerWorks Россия  >  SOA и Web-сервисы | XML  >

Service Data Objects (SDO) 2.0: Создание и чтение документа XML на основе схемы XML

developerWorks
Опции документа

Опции документа, требующие включения JavaScript, не отображаются

Обсудить


Выскажите мнение об этой странице

Помогите нам улучшить содержание


Уровень сложности: простой

Фувей Луо, разработчик, IBM Software Group, подразделение Application and Integration Middleware Software, IBM

05.10.2007

Узнайте о преимуществах API SDO 2.0, выполнив простые примеры. (Обновлено, исправлен Листинг 1 - ред.)

Введение: Что такое SDO?

Service Data Object (SDO, Объекты служебных данных) 2.0 - это API-интерфейс программирования моделей данных, построенный на основе открытого стандарта, который позволяет разработчикам с легкостью манипулировать данными на высоком уровне. Хотя версия SDO 1.0 направлена на те же задачи абстрагирования данных, у нее есть ряд значительных недостатков, основным из которых является отсутствие классов helper, таких как XSDHelper, XMLHelper и т.п. В итоге разработчик вынужден использовать интерфейсы реализации SDO 1.0, происходящие из SDK среды моделирования Eclipse Modeling Framework (EMF).

В текущей реализации SDO 2.0 используется SDK EMF 2.2, но эта особенность реализации не влияет на написание программ для нового API. В будущем сообщество разработчиков ПО с открытым исходным кодом в рамках Apache Software Foundation может принять решение об изменении реализации SDO 2.0, но это не должно повлиять на приложения, использующие интерфейсы API SDO 2.0.

Самый простой способ продемонстрировать преимущества нового API - использовать SDO 2.0 для создания и последующего чтения документа XML, совместимого со схемой XML (XSD). Чтобы сделать это без SDO 2.0, разработчик должен был бы понимать, как работает парсер XML, и тесно интегрировать логику анализа данных в приложение. Позже, при изменении XSD, необходимо было бы внести в приложение множество изменений, что подвергает опасности качество кода.

Новым пользователям API SDO 2.0 будет сложно понять его основные идеи путем простого изучения спецификации. Чтобы помочь им, я создал пример из Учебника по схеме XML для начинающих (см. раздел Ресурсы), объясняющий использование API SDO 2.0 для:

  • Записи на диск документа XML и
  • Его чтения.

Сценарий: сбор и предоставление информации о заказах на покупку

Попробуем реализовать этот сценарий в нашем примере. Для начала компания определяет требования к информации, содержащейся в заказах на покупку (PO). После этого мы начинаем создавать статическую форму для структурирования информации. В базах данных такая статическая форма называется схемой таблицы. В XML эта статическая форма называется схемой XML (XSD). Позже, если потребуется собрать какую-либо дополнительную информацию о клиенте, нам будет нужно изменить форму/схему таблицы/XSD.

При размещении заказа клиент должен заполнить форму заказа или предоставить эту информацию оператору, заполняющему форму. Впоследствии информация этой формы будет использоваться компанией для доставки заказа.

После того как компания получит информацию о заказе, она, вероятнее всего, сохранит ее и впоследствии будет использовать, например, для поддержки клиента. В этом примере мы можем сохранить информацию в формате XML и затем прочесть её с помощью API SDO.

На рисунке 1 показан пример информации заказа, полученной от клиента Robert Smith. Для структурирования этого образца заказа создадим файл XSD. Пример заказа создается с помощью программы CreatePurchaseOrder.java в формате XML под названием po.xml. Наконец, с помощью ReadPurchaseOrder.java мы демонстрируем процесс чтения информации о заказе из po.xml.


Рисунок 1. Пример информации о заказе, полученной от Robert Smith
Order date: 1999-10-20

Shipping information:
Name: Alice Smith
Street: 123 Maple Street
City: Mill Valley
State: CA
Zip code: 90952
Country: US

Billing information:
Name: Robert Smith
Street: 8 Oak Avenue
City: Mill Valley
State: PA
Zip code: 95819
Country: US

Order Items:
1. Part number: 872-AA
Product name: Lawnmower
Quantity: 1
Price: 148.95
Comment: Confirm this is electric

2. Part number: 926-AA
Product name: Baby Monitor
Quantity: 1
Price: 39.98
Ship date: 1999-05-21

Comment: Hurry, my lawn is going wild!



В начало


Схема XML заказа на покупку

На основе примера заказа на покупку, показанного на Рисунке 1, мы можем создать специальный тип данных для заказов на покупку. Давайте назовем его PurchaseOrderType. Экземпляр PurchaseOrderType может содержать четыре основных раздела данных:

  1. shipping information
  2. billing information
  3. order items information
  4. comment

Информация о доставке (shipping information) и оплате (billing information) может содержать дополнительные данные, например, name, street, city, state, zip и country. В информации о заказе (order items information) может содержаться множество данных о товарах, заказанных клиентом. Для каждой позиции может указываться part number, product name, quantity, price, ship date и comment. В области примечаний (comment) содержится строковое значение, дополнительное структурирование этой информации не требуется.

В Листинге 1 показана вся информация о заказе в файле, структурированном в формате XSD.


Листинг 1. PO.xsd

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://www.example.com/PO" targetNamespace="http://www.example.com/PO">

    <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
    <xsd:element name="comment" type="xsd:string"/>

    <xsd:complexType name="PurchaseOrderType">
        <xsd:sequence>
            <xsd:element name="shipTo" type="USAddress"/>
            <xsd:element name="billTo" type="USAddress"/>
            <xsd:element ref="comment" minOccurs="0"/>
            <xsd:element name="items"  type="Items"/>
        </xsd:sequence>
        <xsd:attribute name="orderDate" type="xsd:date"/>
    </xsd:complexType>

    <xsd:complexType name="USAddress">
        <xsd:sequence>
            <xsd:element name="name"   type="xsd:string"/>
            <xsd:element name="street" type="xsd:string"/>
            <xsd:element name="city"   type="xsd:string"/>
            <xsd:element name="state"  type="xsd:string"/>
            <xsd:element name="zip"    type="xsd:decimal"/>
        </xsd:sequence>
        <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
    </xsd:complexType>

    <xsd:complexType name="Items">
        <xsd:sequence>
            <xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="productName" type="xsd:string"/>
                        <xsd:element name="quantity">
                            <xsd:simpleType>
                                <xsd:restriction base="xsd:positiveInteger">
                                    <xsd:maxExclusive value="100"/>
                                </xsd:restriction>
                            </xsd:simpleType>
                        </xsd:element>
                        <xsd:element name="USPrice"  type="xsd:decimal"/>
                        <xsd:element ref="comment"   minOccurs="0"/>
                        <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
                    </xsd:sequence>
                    <xsd:attribute name="partNum" type="SKU" use="required"/>
                </xsd:complexType>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:simpleType name="SKU">
        <xsd:restriction base="xsd:string">
            <xsd:pattern value="\d{3}-[A-Z]{2}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>


Также для структурирования информации заказа можно использовать диаграмму классов унифицированного языка моделирования (UML), показанную на Рисунке 2.


Рисунок 2. Диаграмма классов UML для заказа на покупку
Диаграмма классов UML для заказа на покупку

Файл XSD po.xsd и диаграмма классов UML имеют несколько отличий:

  1. В диаграмме классов определен тип ItemType, который не определяется в po.xsd.diagram. Несмотря на то, что po.xsd не определяет ItemType напрямую, спецификация XSD обрабатывает ItemType как анонимный тип.
  2. Все xsd:<type> в файле XSD сокращаются до <type> в диаграмме классов. В файле XSD часть xsd шаблона xsd:<type> используется для обозначения пространства имен, к которому принадлежит тип. В диаграмме классов для простоты мы это указание опускаем.
  3. SKU type в диаграмме классов не определяется. SKU type фактически является нормализованным строковым типом, определенным в пространстве имен po. В диаграмме классов он представлен типом string type.


В начало


Создание примера заказа в XML

Пример программы CreatePurchaseOrder.java, показанный в Листинге 2, создает заказ на покупку в формате XML под названием po.xml, приведенный в Листинге 3.


Листинг 2. CreatePurchaseOrder.java
/**
 * Author:	Fuhwei Lwo
 */
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.OutputStream;

import commonj.sdo.DataObject;
import commonj.sdo.helper.DataFactory;
import commonj.sdo.helper.XMLHelper;
import commonj.sdo.helper.XSDHelper;

public class CreatePurchaseOrder {
  private static final String PO_MODEL = "po.xsd";
  private static final String PO_NAMESPACE = "http://www.example.com/PO";
  private static final String PO_XML = "po.xml";

	private static void definePOTypes() throws Exception {
	 FileInputStream fis = new FileInputStream(PO_MODEL);
	 XSDHelper.INSTANCE.define(fis, null);
	 fis.close();
	}

	public static void main(String[] args) throws Exception {
	 definePOTypes();
      
	 DataObject purchaseOrder = 
	   DataFactory.INSTANCE.create(PO_NAMESPACE, "PurchaseOrderType");
		
	 purchaseOrder.setString("orderDate", "1999-10-20");
		
	 DataObject shipTo = purchaseOrder.createDataObject("shipTo");
	 shipTo.set("country", "US");
	 shipTo.set("name", "Alice Smith");
	 shipTo.set("street", "123 Maple Street");
	 shipTo.set("city", "Mill Valley");
	 shipTo.set("state", "CA");
	 shipTo.setString("zip", "90952");
	 DataObject billTo = purchaseOrder.createDataObject("billTo");
	 billTo.set("country", "US");
	 billTo.set("name", "Robert Smith");
	 billTo.set("street", "8 Oak Avenue");
	 billTo.set("city", "Mill Valley");
	 billTo.set("state", "PA");
	 billTo.setString("zip", "95819");
	 purchaseOrder.set("comment", "Hurry, my lawn is going wild!");
		
	 DataObject items = purchaseOrder.createDataObject("items");
		
	 DataObject item1 = items.createDataObject("item");
	 item1.set("partNum", "872-AA");
	 item1.set("productName", "Lawnmower");
	 item1.setInt("quantity", 1);
	 item1.setString("USPrice", "148.95");
	 item1.set("comment", "Confirm this is electric");
		
	 DataObject item2 = items.createDataObject("item");
	 item2.set("partNum", "926-AA");
	 item2.set("productName", "Baby Monitor");
	 iteim2.setInt("quantity", 1);
	 item2.setString("USPrice", "39.98");
	 item2.setString("shipDate", "1999-05-21");
		
	 OutputStream stream = new FileOutputStream(PO_XML);
	 XMLHelper.INSTANCE.save(purchaseOrder, PO_NAMESPACE, "purchaseOrder", stream);
	}
}


Листинг 3. Po.xml
<?xml version="1.0" encoding="ASCII"?>
<po:purchaseOrder xmlns:po="http://www.example.com/PO" orderDate="1999-10-20">
  <shipTo country="US">
    <name>Alice Smith</name>
    <street>123 Maple Street</street>
    <city>Mill Valley</city>
    <state>CA</state>
    <zip>90952</zip>
  </shipTo>
  <billTo country="US">
    <name>Robert Smith</name>
    <street>8 Oak Avenue</street>
    <city>Mill Valley</city>
    <state>PA</state>
    <zip>95819</zip>
  </billTo>
  <comment>Hurry, my lawn is going wild!</comment>
  <items>
    <item partNum="872-AA">
      <productName>Lawnmower</productName>
      <quantity>1</quantity>
      <USPrice>148.95</USPrice>
      <comment>Confirm this is electric</comment>
    </item>
    <item partNum="926-AA">
      <productName>Baby Monitor</productName>
      <quantity>1</quantity>
      <USPrice>39.98</USPrice>
      <shipDate>1999-05-21</shipDate>
    </item>
  </items>
</po:purchaseOrder>

Этот пример программы на Java сначала регистрирует все типы, описанные в po.xsd, используя рабочую среду SDO и вызывая метод XSDHelper.INSTANCE.define(). После этого создается корневой документ DataObject типа PurchaseOrderType. При этом с помощью используется API DataObject строится дерево DataObject, представляющее информацию о заказе, показанное на рисунке 3, .


Рисунок 3. Дерево DataObject
Дерево DataObject

Каждый прямоугольник на Рисунке 3 состоит из двух частей. Верхняя часть (серого цвета) обозначает название экземпляра DataObject и его реальный тип; в нижней части показаны содержащиеся в нем свойства. Например, корневым объектом дерева является экземпляр purchaseOrder DataObject; его реальный тип - PurchaseOrderType, который определен в PO.xsd в Листинге 1. В этом экземпляре DataObject содержится два значения свойств – orderDate и comment.

После создания дерева DataObject программа вызывает метод XMLHelper.INSTANCE.save(), сохраняя содержимое дерева, начиная с экземпляра purchaseOrder DataObject, в документ XML - в данном случае po.xml. На самом деле в качестве первого параметра метода XMLHelper.INSTANCE.save() вы можете указать любой экземпляр DataObject из дерева, и метод save() сохранит все экземпляры DataObject, начиная с указанного.



В начало


Чтение примера заказа

После того, как CreatePurchaseOrder.java создаст файл po.xml, мы можем скомпилировать и запустить программу ReadPurchaseOrder.java, представленную в Листинге 4, чтобы продемонстрировать использование API SDO для чтения содержимого файла po.xml. Приложение выполняет следующие действия:

  1. Проверяет, зарегистрированы ли типы, определенные в po.xsd, в среде SDO
  2. Вызывает метод XMLHelper.load() для загрузки в память файла po.xml, который представляется экземпляром XMLDocument xmlDoc
  3. Вызывает метод xmlDoc.getRootObject() для извлечения корневого объекта DataObject дерева purchaseOrder, соответствующего purchaseOrder DataObject в дереве DataObject диаграммы, показанной на Рисунке 3
  4. После того получения purchaseOrder DataObject программа проходит по дереву DataObjectи извлекает всю информацию об этом заказе

Листинг 4. ReadPurchaseOrder.java
/**
/**
 * Author:	Fuhwei Lwo
 */
import java.io.FileInputStream;
import java.util.List;

import commonj.sdo.DataObject;
import commonj.sdo.helper.XMLDocument;
import commonj.sdo.helper.XMLHelper;
import commonj.sdo.helper.XSDHelper;


public class ReadPurchaseOrder {
 private static final String PO_MODEL = "po.xsd";
 private static final String PO_XML = "po.xml";

	private static void definePOTypes() throws Exception {
	  FileInputStream fis = new FileInputStream(PO_MODEL);
	  XSDHelper.INSTANCE.define(fis, null);
	  fis.close();
        }

	public static void main(String[] args) throws Exception {
 	  definePOTypes();

 	  FileInputStream fis = new FileInputStream(PO_XML);

 	  XMLDocument xmlDoc = XMLHelper.INSTANCE.load(fis);

 	  DataObject purchaseOrder = xmlDoc.getRootObject();
 	  
           System.out.println("Order date: " + purchaseOrder.get("orderDate"));
          System.out.println("Comment: " + purchaseOrder.get("comment"));

 	  DataObject shipTo = purchaseOrder.getDataObject("shipTo");
 	  System.out.println("Ship to name: " + shipTo.get("name"));

	  DataObject billTo = purchaseOrder.getDataObject("billTo");
           System.out.println("Bill to name: " + billTo.get("name"));
          System.out.println();

            DataObject items = purchaseOrder.getDataObject("items");
            List itemList = items.getList("item");
            for (int i=0; i<itemList.size(); i++) {
        
		       DataObject item = (DataObject)itemList.get(i);
			
		       System.out.println("Part num: " + item.get("partNum"));S
		      System.out.println("Product name: " + item.get("productName"));
    } // for
  }
}

System.out.println(), выделенный жирным шрифтом в Листинге 4, показывает значения свойств различных объектов данных, в число которых входят:

  • orderDate и comment - свойства purchaseOrder DataObject
  • name - свойства shipTo DataObject
  • name - свойства billTo DataObject
  • partNum и productName - параметры различных объектов данных

Рисунок 4. Вывод результатов работы ReadPurchaseOrder на консоль
Order date: 1999-10-20

Comment: Hurry, my lawn is going wild!
Ship to name: Alice Smith
Bill to name: Robert Smith

Part num: 872-AA
Product name: Lawnmower

Part num: 926-AA
_Product name: Baby monitor _

На Рисунке 4 можно увидеть результат работы кода Java ReadPurchaseOrder.



В начало


Заключение: SDO может стать фактическим стандартом API-интерфейса программирования модели данных

Интерфейсы SDO 2.0 предоставляют единообразный способ создания данных и доступа к ним, а также избавляют разработчиков от необходимости подробной разработки процедур парсинга и поддержки целостности данных. На сегодняшний день SDO 2.0 является инкубаторным субпроектом (под названием Tuscany) организации Apache Software Foundation, цель которого - стать де-факто стандартным интерфейсом программирования моделей данных для разработки SOA. Ссылки можно найти в разделе Ресурсы.

Как можно видеть из приведенных выше примеров, интерфейсы SDO 2.0 полностью избавляют вас от необходимости знания и использования API парсера XML для чтения, записи и управления данными. Если вы создаете на Java DataObject, представляющий данные XML в соответствии с определенной вами схемой XML, SDO 2.0 обеспечивает вам удобство и гибкость, позволяя сконцентрироваться непосредственно на работе с данными. В результате этот API предоставляет значительные преимущества, заключающиеся в повышении производительности разработки и качества продукта.

Таким образом, использование технологии абстрагирования данных, реализованной в SDO 2.0, позволяет вам трактовать данные в соответствии с определенной вами бизнес-логикой, чтобы решать задачи бизнеса. Это помогает упростить разработку бизнес-приложений и повысить продуктивность вашей команды и качество ее работы.



Ресурсы

Научиться

Обсудить


Об авторе

Фувей Луо (Fuhwei Lwo) - руководитель группы разработки Объектов служебных данных (Service Data Objects, SDO) WebSphere в IBM Software Group. Основной его целью является обеспечение успешного принятия SDO в качестве API программирования моделей данных в сервис-ориентированной архитектуре (SOA).




Выскажите мнение об этой странице


Пожалуйста, найдите минутку и заполните форму, чтобы повысить уровень сервиса.



ДаНетНе знаю
 


 


12345
 


В начало


IBM обладает всеми авторскими правами касательно информации, расположенной на developerWorks. Использование информации приведенной на этом ресурсе без явного письменного разрешения от IBM или первоначального автора запрещены. Если Вы желаете использовать информацию с developerWorks, пожалуйста воспользуйтесь регистрационной формой для того, чтобы связаться с нами запрос на использование материалов developerWorks Россия.

    IBM в России Конфиденциальность Контакты