суббота, 25 июня 2011 г.

К вопросам обработки XML-сообщений в Oracle SOA Suite


Одним из вариантов интеграции информационных систем является построение среды обмена сообщениями между данными системами. Так сложилось, что стандартом де-факто для представления сообщений является XML и его многочисленные подмножества. При передаче сообщений между системами зачастую приходится их определенным образом трансформировать - преобразовывать из одних XML-форматов в другие. Такая трансформация может осуществляться различными способами, самыми популярными из которых является применение XSLT, а так же активности Assign в BPEL.

Зачастую перед непосредственно трансформацией сообщения необходимо произвести его разбор: преобразовать из строки в объект, описывающий XML-документ. В Oracle SOA Suite для такого преобразования служит функция oraext:parseXML. Данная функция возвращает объект, который можно присвоить BPEL-переменной.

Здесь и начинаются сложности. Дело в том, что любая BPEL-переменная должна иметь тип. Тип переменной за исключением т.н. простых типов (строка, число, логическое значение) определяется XML-схемой. В дальнейшем все манипуляции с переменной описываются с помощью XPath-выражений, которые в среде разработки (JDeveloper) строятся так же на основании типа переменной, т.е. в конечном итоге - на основании схемы. В связи с этим хочется рассмотреть два вопроса:

1. Что произойдет, если на вход функции oraext:parseXML подать строку, представляющую собой XML, не соответствующий схеме.

2. Как влияют определения пространств имен на соответствие XML-документа схеме.

Ответ на первый вопрос следующий: если строка представляет собой корректный с точки зрения синтаксиса XML, то она будет разобрана и присвоена переменной без каких-либо проблем. Однако, производить XPath-манипуляции над такой переменной будет невозможно, потому что сгенерированные во время разработки XPath-выражения предназначены для работы с XML-переменной, соответствующей другой схеме.

Второй вопрос вызван тем, что при подключении информационной системы к интеграционному решению не всегда можно влиять на формат генерируемых данной системой сообщений. В частности, не всегда генерируемые сообщения содержат информацию о пространстве имен, поэтому в XSD-документе нужно правильно выбирать значение параметра elementFormDefault: qualified или unqualified.

В общем случае разница между двумя данными значениями следующая: при qualified схеме каждый элемент XML-документа должен входить в целевое пространство имен схемы. Если пространство имен задается в виде префикса (xmlns:ns="http://samolisov.blogspot.com/oracle/xml"), то каждый элемент документа, описанный в интересующей нас схеме, должен начинаться с данного префикса.

  1. <ns1:message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
  2.   <ns1:header>
  3.      header
  4.   </ns1:header>
  5.   <ns1:body>
  6.      body
  7.   </ns1:body>
  8. </ns1:message>
  9.  


При unqualified схеме в целевое пространство имен схемы входит только корневой элемент. Т.е. в случае использования префикса пространства имен только данный элемент должен иметь такой префикс. Его дочерние элементы должны быть описаны без префикса.

  1. <ns:message xmlns:ns="http://samolisov.blogspot.com/oracle/xml">
  2.   <header>
  3.      header
  4.   </header>
  5.   <body>
  6.      body
  7.   </body>
  8. </ns:message>
  9.  


Однако в Oracle SOA Suite есть одна особенность: при разборе сообщения функцией oraext:parseXML и присваивании результата переменной, фактический корневой тег сообщения отбрасывается, а вместо него подставляется корневой тег, определенный в схеме, описывающей тип переменной.

Т.е. если определить переменную var, тип которой описывается схемой:

  1. <?xml version="1.0" encoding="windows-1251" ?>
  2. <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  3.            xmlns:rt="http://samolisov.blogspot.com/oracle/xml"
  4.            targetNamespace="http://samolisov.blogspot.com/oracle/xml"
  5.            elementFormDefault="qualified">
  6.   <xsd:element name="message">    
  7.     <xsd:complexType>
  8.         <xsd:sequence>
  9.             <xsd:element name="header" type="xsd:string"></xsd:element>
  10.             <xsd:element name="body" type="xsd:string"></xsd:element>
  11.         </xsd:sequence>
  12.     </xsd:complexType>
  13.   </xsd:element>
  14. </xsd:schema>
  15.  


И на вход функции oraext:parseXML подать строку:

  1. <ns:message1 xmlns:ns="http://samolisov.blogspot.com/oracle/xml"><ns:header>header</ns:header><ns:body>body</ns:body></ns:message1>


То значение переменной var будет следующим:

  1. <var>
  2.   <message>
  3.     <ns:header>header</ns:header>
  4.     <ns:body>body</ns:body>
  5.   </message>
  6. </var>
  7.  


И это несмотря на то, что в качестве корневого элемента во входной строке использовалось message1, а не message.

Подводя итог, рассмотрим результат обработки различных сообщений, соответствующих одной и той же схеме, имеющей только разные значения параметра elementFormDefault: qualified и unqualified, соответственно. Алгоритм обработки сообщений прост: конвертация строки сообщения в XML-переменную и извлечение из XML-переменной значения элемента header. Под результатом обработки будем понимать лишь факт успешного (+) или неуспешного (-) извлечения значения элемента header.

Сообщение 1:
  1. <ns1:message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
  2.   <ns1:header>
  3.      header
  4.   </ns1:header>
  5.   <ns1:body>
  6.      body
  7.   </ns1:body>
  8. </ns1:message>
  9.  


Сообщение 2:
  1. <message>
  2.   <header>
  3.      header
  4.   </header>
  5.   <body>
  6.      body
  7.   </body>
  8. </message>
  9.  


Сообщение 3:
  1. <ns1:message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
  2.   <header>
  3.      header
  4.   </header>
  5.   <body>
  6.      body
  7.   </body>
  8. </ns1:message>


Сообщение 4:
  1. <message xmlns="http://samolisov.blogspot.com/oracle/xml">
  2.   <header>
  3.      header
  4.   </header>
  5.   <body>
  6.      body
  7.   </body>
  8. </message>
  9.  


Сообщение 5:
  1. <message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
  2.   <header>
  3.      header
  4.   </header>
  5.   <body>
  6.      body
  7.   </body>
  8. </message>
  9.  


Сообщение 6:
  1. <message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
  2.   <ns1:header>
  3.      header
  4.   </ns1:header>
  5.   <ns1:body>
  6.      body
  7.   </ns1:body>
  8. </message>
  9.  


Результат:
Сообщение        qualified           unqualified
1                +                   - 
2                -                   +
3                -                   +
4                +                   - 
5                -                   +
6                +                   - 


Понравилось сообщение - подпишитесь на блог

Комментариев нет:

Отправить комментарий

Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!