Одним из вариантов интеграции информационных систем является построение среды обмена сообщениями между данными системами. Так сложилось, что стандартом де-факто для представления сообщений является 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"), то каждый элемент документа, описанный в интересующей нас схеме, должен начинаться с данного префикса.
- <ns1:message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
- <ns1:header>
- header
- </ns1:header>
- <ns1:body>
- body
- </ns1:body>
- </ns1:message>
При unqualified схеме в целевое пространство имен схемы входит только корневой элемент. Т.е. в случае использования префикса пространства имен только данный элемент должен иметь такой префикс. Его дочерние элементы должны быть описаны без префикса.
- <ns:message xmlns:ns="http://samolisov.blogspot.com/oracle/xml">
- <header>
- header
- </header>
- <body>
- body
- </body>
- </ns:message>
Однако в Oracle SOA Suite есть одна особенность: при разборе сообщения функцией oraext:parseXML и присваивании результата переменной, фактический корневой тег сообщения отбрасывается, а вместо него подставляется корневой тег, определенный в схеме, описывающей тип переменной.
Т.е. если определить переменную var, тип которой описывается схемой:
- <?xml version="1.0" encoding="windows-1251" ?>
- <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:rt="http://samolisov.blogspot.com/oracle/xml"
- targetNamespace="http://samolisov.blogspot.com/oracle/xml"
- elementFormDefault="qualified">
- <xsd:element name="message">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="header" type="xsd:string"></xsd:element>
- <xsd:element name="body" type="xsd:string"></xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- </xsd:schema>
И на вход функции oraext:parseXML подать строку:
- <ns:message1 xmlns:ns="http://samolisov.blogspot.com/oracle/xml"><ns:header>header</ns:header><ns:body>body</ns:body></ns:message1>
То значение переменной var будет следующим:
- <var>
- <message>
- <ns:header>header</ns:header>
- <ns:body>body</ns:body>
- </message>
- </var>
И это несмотря на то, что в качестве корневого элемента во входной строке использовалось message1, а не message.
Подводя итог, рассмотрим результат обработки различных сообщений, соответствующих одной и той же схеме, имеющей только разные значения параметра elementFormDefault: qualified и unqualified, соответственно. Алгоритм обработки сообщений прост: конвертация строки сообщения в XML-переменную и извлечение из XML-переменной значения элемента header. Под результатом обработки будем понимать лишь факт успешного (+) или неуспешного (-) извлечения значения элемента header.
Сообщение 1:
- <ns1:message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
- <ns1:header>
- header
- </ns1:header>
- <ns1:body>
- body
- </ns1:body>
- </ns1:message>
Сообщение 2:
- <message>
- <header>
- header
- </header>
- <body>
- body
- </body>
- </message>
Сообщение 3:
- <ns1:message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
- <header>
- header
- </header>
- <body>
- body
- </body>
- </ns1:message>
Сообщение 4:
- <message xmlns="http://samolisov.blogspot.com/oracle/xml">
- <header>
- header
- </header>
- <body>
- body
- </body>
- </message>
Сообщение 5:
- <message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
- <header>
- header
- </header>
- <body>
- body
- </body>
- </message>
Сообщение 6:
- <message xmlns:ns1="http://samolisov.blogspot.com/oracle/xml">
- <ns1:header>
- header
- </ns1:header>
- <ns1:body>
- body
- </ns1:body>
- </message>
Результат:
Сообщение qualified unqualified 1 + - 2 - + 3 - + 4 + - 5 - + 6 + -
Понравилось сообщение - подпишитесь на блог
Комментариев нет:
Отправить комментарий
Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!